From 0d96b4df8af0c553a857f58147c8e2fe850f0998 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Tue, 16 Jan 2024 15:52:03 +0900 Subject: [PATCH 001/356] =?UTF-8?q?[Feat]=20Benefit=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Benefit과 BenefitType을 설정했습니다. --- .../domain/benefit/domain/Benefit.java | 29 ++++++++++++++++--- .../domain/benefit/domain/BenefitType.java | 5 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index 29cd7027..2129726a 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -1,15 +1,36 @@ package com.ttubeog.domain.benefit.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; +import lombok.*; +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter @Entity +@Table(name = "benefit") public class Benefit extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "content") + private String content; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private BenefitType type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + @Builder + public Benefit(Long id, String content, BenefitType type, Store store) { + this.id = id; + this.content = content; + this.type = type; + this.store = store; + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java b/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java new file mode 100644 index 00000000..41dcbc5f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java @@ -0,0 +1,5 @@ +package com.ttubeog.domain.benefit.domain; + +public enum BenefitType { + sale, plus, gift +} From 056f6982608595cefb7d74df7b8bdf8d900c6199 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Tue, 16 Jan 2024 15:57:14 +0900 Subject: [PATCH 002/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9D=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 혜택 생성 api를 작성했습니다. Store은 아직 완성이 안된 상태라 주석처리했습니다. --- .../benefit/application/BenefitService.java | 55 +++++++++++++++++++ .../benefit/dto/request/CreateBenefitReq.java | 22 ++++++++ .../dto/response/CreateBenefitRes.java | 31 +++++++++++ .../presentation/BenefitController.java | 39 ++++++++++++- 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java create mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index a6d821cb..38a53b93 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -1,11 +1,66 @@ package com.ttubeog.domain.benefit.application; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; +import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.global.DefaultAssert; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) public class BenefitService { + + private final MemberRepository memberRepository; + private final BenefitRepository benefitRepository; + private final StoreRepository storeRepository; + + // 혜택 생성 + @Transactional + public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { + + Optional userOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(userOptional); + Member member = userOptional.get(); + +// Optional storeOptional = storeRepository.findById(createBenefitReq.getStoreId()); +// Store store; +// DefaultAssert.isOptionalPresent(storeOptional); +// store = storeOptional.get(); + + Benefit benefit = Benefit.builder() + .content(createBenefitReq.getContent()) + .type(createBenefitReq.getType()) +// .store(store) + .build(); + + benefitRepository.save(benefit); + + CreateBenefitRes createBenefitRes = CreateBenefitRes.builder() + .benefitId(benefit.getId()) +// .storeId(benefit.getStore().getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(createBenefitRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java new file mode 100644 index 00000000..23f88161 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java @@ -0,0 +1,22 @@ +package com.ttubeog.domain.benefit.dto.request; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigInteger; + +@Data +@Schema(description = "BenefitRequest") +public class CreateBenefitReq { + +// @Schema(description = "매장 ID", example = "1") +// private Long storeId; + + @Schema(description = "내용", example = "아메리카노 20% 할인") + private String content; + + @Schema(description = "혜택타입", example = "sale") + private BenefitType type; + +} diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java new file mode 100644 index 00000000..b7190e55 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java @@ -0,0 +1,31 @@ +package com.ttubeog.domain.benefit.dto.response; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class CreateBenefitRes { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + +// @Schema(description = "매장 ID", example = "1") +// private Long storeId; + + @Schema(description = "내용", example = "아메리카노 20% 할인") + private String content; + + @Schema(description = "혜택타입", example = "sale") + private BenefitType type; + + @Builder +// public CreateBenefitRes(Long benefitId, Long storeId, String content, BenefitType type) { + public CreateBenefitRes(Long benefitId, String content, BenefitType type) { + this.benefitId = benefitId; +// this.storeId = storeId; + this.content = content; + this.type = type; + } +} diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index d75ea3a6..a4fca372 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -1,7 +1,44 @@ package com.ttubeog.domain.benefit.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.application.BenefitService; +import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; +import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ErrorResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Benefit", description = "Benefit API") @RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/benefit") public class BenefitController { + + private final BenefitService benefitService; + + //혜택 생성 + @Operation(summary = "혜택 생성", description = "매장의 혜택을 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PostMapping + public ResponseEntity createBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CreateBenefitReq createBenefitReq + ) throws JsonProcessingException { + return benefitService.createBenefit(userPrincipal, createBenefitReq); + } } From 13751fe8940873767af7a8aef3ac51a8b65fc003 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 16 Jan 2024 17:26:51 +0900 Subject: [PATCH 003/356] =?UTF-8?q?[FEAT]=20User=20->=20Member=EB=A1=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=88=98=EC=A0=95=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomDefaultOAuth2UserService.java | 14 ++++++------- ...e.java => CustomMemberDetailsService.java} | 10 +++++----- .../CustomTokenProviderService.java | 20 +++++++++---------- .../auth/controller/OauthController.java | 9 +++++++++ .../member/application/MemberService.java | 6 +++--- .../member/presentation/MemberController.java | 8 ++++---- .../config/security/SecurityConfig.java | 6 +++--- .../{CurrentUser.java => CurrentMember.java} | 2 +- ...serPrincipal.java => MemberPrincipal.java} | 16 +++++++-------- 9 files changed, 50 insertions(+), 41 deletions(-) rename src/main/java/com/ttubeog/domain/auth/application/{CustomUserDetailsService.java => CustomMemberDetailsService.java} (79%) create mode 100644 src/main/java/com/ttubeog/domain/auth/controller/OauthController.java rename src/main/java/com/ttubeog/global/config/security/token/{CurrentUser.java => CurrentMember.java} (89%) rename src/main/java/com/ttubeog/global/config/security/token/{UserPrincipal.java => MemberPrincipal.java} (80%) diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java index 318adc6c..5e7d7577 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java @@ -7,7 +7,7 @@ import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.auth.OAuth2UserInfo; import com.ttubeog.global.config.security.auth.OAuth2UserInfoFactory; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.config.security.token.MemberPrincipal; import lombok.RequiredArgsConstructor; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; @@ -37,21 +37,21 @@ public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2Aut private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); DefaultAssert.isAuthentication(!oAuth2UserInfo.getEmail().isEmpty()); - + Optional userOptional = memberRepository.findByEmail(oAuth2UserInfo.getEmail()); Member member; if(userOptional.isPresent()) { member = userOptional.get(); DefaultAssert.isAuthentication(member.getProvider().equals(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))); - member = updateExistingUser(member, oAuth2UserInfo); + member = updateExistingMember(member, oAuth2UserInfo); } else { - member = registerNewUser(oAuth2UserRequest, oAuth2UserInfo); + member = registerNewMember(oAuth2UserRequest, oAuth2UserInfo); } - return UserPrincipal.create(member, oAuth2User.getAttributes()); + return MemberPrincipal.create(member, oAuth2User.getAttributes()); } - private Member registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { + private Member registerNewMember(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { Member member = Member.builder() .provider(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())) .providerId(oAuth2UserInfo.getId()) @@ -64,7 +64,7 @@ private Member registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserIn return memberRepository.save(member); } - private Member updateExistingUser(Member member, OAuth2UserInfo oAuth2UserInfo) { + private Member updateExistingMember(Member member, OAuth2UserInfo oAuth2UserInfo) { member.updateName(oAuth2UserInfo.getName()); member.updateImageUrl(oAuth2UserInfo.getImageUrl()); diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomUserDetailsService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java similarity index 79% rename from src/main/java/com/ttubeog/domain/auth/application/CustomUserDetailsService.java rename to src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java index 59c10ed6..a8b63c67 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomUserDetailsService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java @@ -3,7 +3,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.config.security.token.MemberPrincipal; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; @@ -15,7 +15,7 @@ @RequiredArgsConstructor @Service -public class CustomUserDetailsService implements UserDetailsService{ +public class CustomMemberDetailsService implements UserDetailsService{ private final MemberRepository memberRepository; @@ -24,10 +24,10 @@ public UserDetails loadUserByUsername(String email) throws UsernameNotFoundExcep Member member = memberRepository.findByEmail(email) .orElseThrow(() -> - new UsernameNotFoundException("유저 정보를 찾을 수 없습니다.") + new UsernameNotFoundException("멤버 정보를 찾을 수 없습니다.") ); - return UserPrincipal.create(member); + return MemberPrincipal.create(member); } @Transactional @@ -35,7 +35,7 @@ public UserDetails loadUserById(Long id) { Optional user = memberRepository.findById(id); DefaultAssert.isOptionalPresent(user); - return UserPrincipal.create(user.get()); + return MemberPrincipal.create(user.get()); } } diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java index eba5acba..a6672c38 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java @@ -2,7 +2,7 @@ import com.ttubeog.domain.auth.dto.TokenMapping; import com.ttubeog.global.config.security.OAuth2Config; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.config.security.token.MemberPrincipal; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; @@ -24,10 +24,10 @@ public class CustomTokenProviderService { private OAuth2Config oAuth2Config; @Autowired - private CustomUserDetailsService customUserDetailsService; + private CustomMemberDetailsService customMemberDetailsService; public TokenMapping refreshToken(Authentication authentication, String refreshToken) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + MemberPrincipal memberPrincipal = (MemberPrincipal) authentication.getPrincipal(); Date now = new Date(); Date accessTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getAccessTokenExpirationMsec()); @@ -37,21 +37,21 @@ public TokenMapping refreshToken(Authentication authentication, String refreshTo Key key = Keys.hmacShaKeyFor(keyBytes); String accessToken = Jwts.builder() - .setSubject(Long.toString(userPrincipal.getId())) + .setSubject(Long.toString(memberPrincipal.getId())) .setIssuedAt(new Date()) .setExpiration(accessTokenExpiresIn) .signWith(key, SignatureAlgorithm.HS512) .compact(); return TokenMapping.builder() - .userEmail(userPrincipal.getEmail()) + .userEmail(memberPrincipal.getEmail()) .accessToken(accessToken) .refreshToken(refreshToken) .build(); } public TokenMapping createToken(Authentication authentication) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + MemberPrincipal memberPrincipal = (MemberPrincipal) authentication.getPrincipal(); Date now = new Date(); @@ -64,7 +64,7 @@ public TokenMapping createToken(Authentication authentication) { Key key = Keys.hmacShaKeyFor(keyBytes); String accessToken = Jwts.builder() - .setSubject(Long.toString(userPrincipal.getId())) + .setSubject(Long.toString(memberPrincipal.getId())) .setIssuedAt(new Date()) .setExpiration(accessTokenExpiresIn) .signWith(key, SignatureAlgorithm.HS512) @@ -76,7 +76,7 @@ public TokenMapping createToken(Authentication authentication) { .compact(); return TokenMapping.builder() - .userEmail(userPrincipal.getEmail()) + .userEmail(memberPrincipal.getEmail()) .accessToken(accessToken) .refreshToken(refreshToken) .build(); @@ -94,13 +94,13 @@ public Long getUserIdFromToken(String token) { public UsernamePasswordAuthenticationToken getAuthenticationById(String token){ Long userId = getUserIdFromToken(token); - UserDetails userDetails = customUserDetailsService.loadUserById(userId); + UserDetails userDetails = customMemberDetailsService.loadUserById(userId); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); return authentication; } public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String email){ - UserDetails userDetails = customUserDetailsService.loadUserByUsername(email); + UserDetails userDetails = customMemberDetailsService.loadUserByUsername(email); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); return authentication; } diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java new file mode 100644 index 00000000..8d16e68b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.auth.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class OauthController { +} diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 943eee8f..b9cc6379 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -4,7 +4,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.config.security.token.MemberPrincipal; import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -20,8 +20,8 @@ public class MemberService { private final MemberRepository memberRepository; // 현재 유저 조회 - public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ - Optional checkUser = memberRepository.findById(userPrincipal.getId()); + public ResponseEntity getCurrentUser(MemberPrincipal memberPrincipal){ + Optional checkUser = memberRepository.findById(memberPrincipal.getId()); DefaultAssert.isOptionalPresent(checkUser); Member member = checkUser.get(); diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 787d6a9d..aa44a65f 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -2,8 +2,8 @@ import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.config.security.token.CurrentMember; +import com.ttubeog.global.config.security.token.MemberPrincipal; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -33,9 +33,9 @@ public class MemberController { }) @GetMapping public ResponseEntity getCurrentUser( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentMember MemberPrincipal memberPrincipal ) { - return memberService.getCurrentUser(userPrincipal); + return memberService.getCurrentUser(memberPrincipal); } } diff --git a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java b/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java index a602429a..a26ab307 100644 --- a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java +++ b/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java @@ -1,7 +1,7 @@ package com.ttubeog.global.config.security; import com.ttubeog.domain.auth.application.CustomDefaultOAuth2UserService; -import com.ttubeog.domain.auth.application.CustomUserDetailsService; +import com.ttubeog.domain.auth.application.CustomMemberDetailsService; import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationFailureHandler; import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationSuccessHandler; @@ -30,7 +30,7 @@ @EnableWebSecurity public class SecurityConfig { - private final CustomUserDetailsService customUserDetailsService; + private final CustomMemberDetailsService customMemberDetailsService; private final CustomDefaultOAuth2UserService customOAuth2UserService; private final CustomSimpleUrlAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; private final CustomSimpleUrlAuthenticationFailureHandler oAuth2AuthenticationFailureHandler; @@ -50,7 +50,7 @@ public CustomOncePerRequestFilter customOncePerRequestFilter() { public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - authenticationProvider.setUserDetailsService(customUserDetailsService); + authenticationProvider.setUserDetailsService(customMemberDetailsService); authenticationProvider.setPasswordEncoder(passwordEncoder()); return authenticationProvider; diff --git a/src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java b/src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java similarity index 89% rename from src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java rename to src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java index 5e48850c..ea1970da 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java +++ b/src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java @@ -8,6 +8,6 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @AuthenticationPrincipal -public @interface CurrentUser { +public @interface CurrentMember { } diff --git a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java similarity index 80% rename from src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java rename to src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java index afc6d046..e222aef5 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java @@ -13,7 +13,7 @@ import java.util.Map; @Getter -public class UserPrincipal implements OAuth2User, UserDetails{ +public class MemberPrincipal implements OAuth2User, UserDetails{ private final Member member; @@ -23,7 +23,7 @@ public class UserPrincipal implements OAuth2User, UserDetails{ private final Collection authorities; private Map attributes; - public UserPrincipal(Member member, Long id, String email, String password, Collection authorities) { + public MemberPrincipal(Member member, Long id, String email, String password, Collection authorities) { this.member = member; this.id = id; this.email = email; @@ -31,9 +31,9 @@ public UserPrincipal(Member member, Long id, String email, String password, Coll this.authorities = authorities; } - public static UserPrincipal create(final Member member) { + public static MemberPrincipal create(final Member member) { List authorities = Collections.singletonList(new SimpleGrantedAuthority(member.getRole().getValue())); - return new UserPrincipal( + return new MemberPrincipal( member, member.getId(), member.getEmail(), @@ -42,10 +42,10 @@ public static UserPrincipal create(final Member member) { ); } - public static UserPrincipal create(Member member, Map attributes) { - UserPrincipal userPrincipal = UserPrincipal.create(member); - userPrincipal.setAttributes(attributes); - return userPrincipal; + public static MemberPrincipal create(Member member, Map attributes) { + MemberPrincipal memberPrincipal = MemberPrincipal.create(member); + memberPrincipal.setAttributes(attributes); + return memberPrincipal; } public void setAttributes(Map attributes) { From 8db6adb995125a0bf68a9a2818b15dd56b3c3e67 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 16 Jan 2024 17:53:37 +0900 Subject: [PATCH 004/356] =?UTF-8?q?[FEAT]=20JWT=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20accessToken,=20refreshToken=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/JwtTokenService.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java new file mode 100644 index 00000000..8c29a7e8 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -0,0 +1,86 @@ +package com.ttubeog.domain.auth.service; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.io.Encoders; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; +import java.util.Random; + +@Service +public class JwtTokenService implements InitializingBean { + + private final String secretKey; + private final long accessTokenExpirationInSeconds; + private final long refreshTokenExpirationInSeconds; + private static Key key; + + + public JwtTokenService( + @Value("${jwt.secret-key}") String secretKey, + @Value("${jwt.access-expired-time}") long accessTokenExpirationInSeconds, + @Value("${jwt.refresh-expired-time}") long refreshTokenExpirationInSeconds + ) { + this.secretKey = secretKey; + this.accessTokenExpirationInSeconds = accessTokenExpirationInSeconds; + this.refreshTokenExpirationInSeconds = refreshTokenExpirationInSeconds; + } + + @Override + public void afterPropertiesSet() throws Exception { + key = getKeyFromBase64EncodedKey(encodeBase64SecretKey(secretKey)); + } + + // JWT 토큰 생성 + public String createToken(String payload, long expireLength) { + // 토큰에 포함될 정보 + Claims claims = Jwts.claims().setSubject(payload); + // 현재 날짜와 시간 + Date now = new Date(); + // 유효기간 + Date validity = new Date(now.getTime() + expireLength); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(key, SignatureAlgorithm.HS256) // 토큰 서명 + .compact(); + } + + // 액세스 토큰 생성 + public String createAccessToken(String payload) { + return createToken(payload, accessTokenExpirationInSeconds); + } + + // 리프레시 토큰 생성 + public String createRefreshToken() { + byte[] array = new byte[7]; + new Random().nextBytes(array); + String newPayload = new String(array, StandardCharsets.UTF_8); + + return createToken(newPayload, refreshTokenExpirationInSeconds); + } + + + + private String encodeBase64SecretKey(String secretKey) { + return Encoders.BASE64.encode(secretKey.getBytes(StandardCharsets.UTF_8)); + } + + private Key getKeyFromBase64EncodedKey(String encodedSecretKey) { + byte[] keyBytes = Decoders.BASE64.decode(encodedSecretKey); + + Key key = Keys.hmacShaKeyFor(keyBytes); + + return key; + } +} From d2cff3b1293ab54bb43f67c03a8da65ac8e7ad35 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Tue, 16 Jan 2024 18:40:07 +0900 Subject: [PATCH 005/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 혜택 삭제 api를 작성했습니다. --- .../benefit/application/BenefitService.java | 29 +++++++++++++++++-- .../presentation/BenefitController.java | 16 ++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 38a53b93..6472e45a 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -12,6 +12,7 @@ import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -32,9 +33,8 @@ public class BenefitService { @Transactional public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { - Optional userOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(userOptional); - Member member = userOptional.get(); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); // Optional storeOptional = storeRepository.findById(createBenefitReq.getStoreId()); // Store store; @@ -63,4 +63,27 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi return ResponseEntity.ok(apiResponse); } + + // 혜택 삭제 + @Transactional + public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + + Optional userOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(userOptional); + + Optional benefitOptional = benefitRepository.findById(benefitId); + DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); + Benefit benefit = benefitOptional.get(); + + benefitRepository.delete(benefit); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("혜택을 삭제했습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + } diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index a4fca372..bde63769 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -7,6 +7,7 @@ import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -41,4 +42,19 @@ public ResponseEntity createBenefit( ) throws JsonProcessingException { return benefitService.createBenefit(userPrincipal, createBenefitReq); } + + //혜택 삭제 + @Operation(summary = "혜택 삭제", description = "매장의 혜택을 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @DeleteMapping("/{benefitId}") + public ResponseEntity deleteBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "benefitId") Long benefitId + ) throws JsonProcessingException { + return benefitService.deleteBenefit(userPrincipal, benefitId); + } } From 72ddce1ea370750a50cdcfcefa6aa7eca539d0e7 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Tue, 16 Jan 2024 20:05:20 +0900 Subject: [PATCH 006/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 혜택 수정 api를 작성했습니다. store가 생기면 추가 작성할 부분을 TODO로 처리했습니다. --- .../benefit/application/BenefitService.java | 31 ++++++++++++++++++ .../domain/benefit/domain/Benefit.java | 4 +++ .../benefit/dto/request/CreateBenefitReq.java | 2 +- .../benefit/dto/request/UpdateBenefitReq.java | 17 ++++++++++ .../dto/response/UpdateBenefitRes.java | 32 +++++++++++++++++++ .../presentation/BenefitController.java | 17 ++++++++++ 6 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java create mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 6472e45a..489e7550 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -4,7 +4,9 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; +import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.store.domain.Store; @@ -85,5 +87,34 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit return ResponseEntity.ok(apiResponse); } + //혜택 수정 + @Transactional + public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { + + Optional userOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(userOptional); + + Optional benefitOptional = benefitRepository.findById(updateBenefitReq.getBenefitId()); + DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); + Benefit benefit = benefitOptional.get(); + + //TODO userOptional과 benefit의 userId가 일치하는지 확인 + + benefit.updateContent(updateBenefitReq.getContent()); + + UpdateBenefitRes updateBenefitRes = UpdateBenefitRes.builder() + .benefitId(benefit.getId()) + //.storeId(benefit.getStore().getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateBenefitRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index 2129726a..a81eae95 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -33,4 +33,8 @@ public Benefit(Long id, String content, BenefitType type, Store store) { this.type = type; this.store = store; } + + public void updateContent(String content) { + this.content = content; + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java index 23f88161..0c9dc671 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java @@ -7,7 +7,7 @@ import java.math.BigInteger; @Data -@Schema(description = "BenefitRequest") +@Schema(description = "CreateBenefitRequest") public class CreateBenefitReq { // @Schema(description = "매장 ID", example = "1") diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java new file mode 100644 index 00000000..52ea336a --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java @@ -0,0 +1,17 @@ +package com.ttubeog.domain.benefit.dto.request; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "UpdateBenefitRequest") +public class UpdateBenefitReq { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "내용", example = "아메리카노 20% 할인") + private String content; + +} diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java new file mode 100644 index 00000000..0bb4044f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java @@ -0,0 +1,32 @@ +package com.ttubeog.domain.benefit.dto.response; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class UpdateBenefitRes { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + +// @Schema(description = "매장 ID", example = "1") +// private Long storeId; + + @Schema(description = "내용", example = "아메리카노 20% 할인") + private String content; + + @Schema(description = "혜택타입", example = "sale") + private BenefitType type; + + @Builder +// public CreateBenefitRes(Long benefitId, Long storeId, String content, BenefitType type) { + public UpdateBenefitRes(Long benefitId, String content, BenefitType type) { + this.benefitId = benefitId; +// this.storeId = storeId; + this.content = content; + this.type = type; + } + +} diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index bde63769..aa619b75 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -3,7 +3,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.application.BenefitService; import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; +import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -57,4 +59,19 @@ public ResponseEntity deleteBenefit( ) throws JsonProcessingException { return benefitService.deleteBenefit(userPrincipal, benefitId); } + + //혜택 수정 + @Operation(summary = "혜택 수정", description = "매장의 혜택을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping + public ResponseEntity updateBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateBenefitReq updateBenefitReq + ) throws JsonProcessingException { + return benefitService.updateBenefit(userPrincipal, updateBenefitReq); + } } From d248648c8fc439d7ed08468333c2d7a8d00f252c Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 02:49:19 +0900 Subject: [PATCH 007/356] =?UTF-8?q?[FEAT]=20KaKao=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?Dto=20=EC=83=9D=EC=84=B1=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../JwtTokenService.java | 2 +- .../auth/application/KakaoOauthService.java | 28 +++++++++++++++++++ .../ttubeog/domain/auth/dto/KakaoInfoDto.java | 19 +++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) rename src/main/java/com/ttubeog/domain/auth/{service => application}/JwtTokenService.java (98%) create mode 100644 src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java diff --git a/build.gradle b/build.gradle index eb5a9b8c..7e687490 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0' testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.3.0' diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java similarity index 98% rename from src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java rename to src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java index 8c29a7e8..a35090fe 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.application; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; diff --git a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java new file mode 100644 index 00000000..fb86ab0d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java @@ -0,0 +1,28 @@ +package com.ttubeog.domain.auth.application; + + +import com.ttubeog.domain.member.application.MemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.Map; + +@RequiredArgsConstructor +@Service +public class KakaoOauthService { + private final MemberService memberService; + + // 카카오 API를 호출해서 AccessToken으로 멤버 정보를 가져오는 로직 + public Map getMemberInfoByToken(String accessToken) { + return WebClient.create() + .get() + .uri("https://kapi.kakao.com/v2/user/me") + .headers(httpHeaders -> httpHeaders.setBasicAuth(accessToken)) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() { + }) + .block(); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java new file mode 100644 index 00000000..e4eb653d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java @@ -0,0 +1,19 @@ +package com.ttubeog.domain.auth.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Map; + +@Getter +@AllArgsConstructor +public class KakaoInfoDto { + private Long id; + private String email; + + public KakaoInfoDto(Map info) { + this.id = Long.valueOf(info.get("id").toString()); + this.email = info.get("email") != null + ? info.get(email).toString() : ""; + } +} From 37b2362dcbb4b229b625253a9fb60a0d74ae759b Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 03:05:51 +0900 Subject: [PATCH 008/356] =?UTF-8?q?[FEAT]=20KaKao=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20DB=EC=97=90=20=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/KakaoOauthService.java | 20 +++++++++++++++++++ .../member/application/MemberService.java | 12 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java index fb86ab0d..60c52773 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.auth.application; +import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.dto.response.MemberDetailRes; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.stereotype.Service; @@ -25,4 +27,22 @@ public Map getMemberInfoByToken(String accessToken) { }) .block(); } + + + // 카카오 API에서 가져온 멤버 정보를 DB 저장, 업데이트 + public MemberDetailRes getMemberProfileByToken(String accessToken) { + Map memberInfoByToken = getMemberInfoByToken(accessToken); + KakaoInfoDto kakaoInfoDto = new KakaoInfoDto(memberInfoByToken); + MemberDetailRes memberDetailRes = MemberDetailRes.builder() + .id(kakaoInfoDto.getId()) + .email(kakaoInfoDto.getEmail()) + .build(); + + if(memberService.findById(memberDetailRes.getId()).isPresent()) { + memberService.update(memberDetailRes); + } else { + memberService.save(memberDetailRes); + } + return memberDetailRes; + } } diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index b9cc6379..30409aef 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -40,4 +40,16 @@ public ResponseEntity getCurrentUser(MemberPrincipal memberPrincipal){ return ResponseEntity.ok(apiResponse); } + public Optional findById(Long id) { + return memberRepository.findById(id); + } + + public void update(MemberDetailRes memberDetailRes) { + + } + + public void save(MemberDetailRes memberDetailRes) { + + } + } From e0af9ec5c773839a8de05183c5a17e4202b9fc92 Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 18:49:08 +0900 Subject: [PATCH 009/356] =?UTF-8?q?[FEAT]=20MemberDto=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EB=B0=8F=20OauthService=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/KakaoOauthService.java | 14 ++++---- .../domain/auth/application/OauthService.java | 36 +++++++++++++++++++ .../member/application/MemberService.java | 15 +++++--- .../ttubeog/domain/member/domain/Member.java | 5 ++- .../ttubeog/domain/member/dto/MemberDto.java | 28 +++++++++++++++ 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/application/OauthService.java create mode 100644 src/main/java/com/ttubeog/domain/member/dto/MemberDto.java diff --git a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java index 60c52773..39266621 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; @@ -30,19 +31,20 @@ public Map getMemberInfoByToken(String accessToken) { // 카카오 API에서 가져온 멤버 정보를 DB 저장, 업데이트 - public MemberDetailRes getMemberProfileByToken(String accessToken) { + public MemberDto getMemberProfileByToken(String accessToken) { Map memberInfoByToken = getMemberInfoByToken(accessToken); KakaoInfoDto kakaoInfoDto = new KakaoInfoDto(memberInfoByToken); - MemberDetailRes memberDetailRes = MemberDetailRes.builder() + MemberDto memberDto = MemberDto.builder() .id(kakaoInfoDto.getId()) .email(kakaoInfoDto.getEmail()) + .platform("kakao") .build(); - if(memberService.findById(memberDetailRes.getId()).isPresent()) { - memberService.update(memberDetailRes); + if(memberService.findById(memberDto.getId()) != null) { + memberService.update(memberDto); } else { - memberService.save(memberDetailRes); + memberService.save(memberDto); } - return memberDetailRes; + return memberDto; } } diff --git a/src/main/java/com/ttubeog/domain/auth/application/OauthService.java b/src/main/java/com/ttubeog/domain/auth/application/OauthService.java new file mode 100644 index 00000000..5bec71e7 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/application/OauthService.java @@ -0,0 +1,36 @@ +package com.ttubeog.domain.auth.application; + +import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.dto.MemberDto; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@RequiredArgsConstructor +@Service +public class OauthService { + private final MemberService memberService; + private final JwtTokenService jwtTokenService; + private final KakaoOauthService kakaoOauthService; + + // 카카오 로그인 + public String loginWithKakao(String accessToken, HttpServletResponse response) { + MemberDto memberDto = kakaoOauthService.getMemberProfileByToken(accessToken); + return getTokens(memberDto.getId(), response); + } + + // 액세스, 리프레시 토큰 생성 + public String getTokens(Long id, HttpServletResponse response) { + final String accessToken = jwtTokenService.createAccessToken(id.toString()); + final String refreshToken = jwtTokenService.createRefreshToken(); + + MemberDto memberDto = memberService.findById(id); + memberDto.setRefreshToken(refreshToken); + memberService.updateRefreshToken(memberDto); + + return accessToken; + } +} diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 30409aef..a79ec70b 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -40,16 +41,22 @@ public ResponseEntity getCurrentUser(MemberPrincipal memberPrincipal){ return ResponseEntity.ok(apiResponse); } - public Optional findById(Long id) { - return memberRepository.findById(id); + public MemberDto findById(Long id) { + Optional optionalMember = memberRepository.findById(id); + + return optionalMember.map(MemberDto::toEntity).orElse(null); } - public void update(MemberDetailRes memberDetailRes) { + + public void save(MemberDto memberDetailRes) { } - public void save(MemberDetailRes memberDetailRes) { + public void update(MemberDto memberDetailRes) { + + } + public void updateRefreshToken(MemberDto memberDetailRes) { } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 2b2b3a1b..da6b439e 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -33,8 +33,10 @@ public class Member extends BaseEntity { private String providerId; + private String platform; + @Builder - public Member(Long id, String name, String email, String imageUrl, Boolean emailVerified, String password, Provider provider, Role role, String providerId) { + public Member(Long id, String name, String email, String imageUrl, Boolean emailVerified, String password, Provider provider, Role role, String providerId, String platform) { this.id = id; this.name = name; this.email = email; @@ -43,6 +45,7 @@ public Member(Long id, String name, String email, String imageUrl, Boolean email this.provider = provider; this.role = role; this.providerId = providerId; + this.platform = platform; } public void updateName(String name){ diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java new file mode 100644 index 00000000..9eefaa7d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -0,0 +1,28 @@ +package com.ttubeog.domain.member.dto; + +import com.ttubeog.domain.member.domain.Member; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +@AllArgsConstructor +public class MemberDto { + private Long id; + private String email; + private String name; + private String platform; + private String refreshToken; + + public static MemberDto toEntity(Member member) { + return MemberDto.builder() + .id(member.getId()) + .email(member.getEmail()) + .name(member.getName()) + .platform(member.getPlatform()) + .build(); + } +} From 039096d382cf58fb717e03f36f9b0bfe0b0ef70f Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 19:43:18 +0900 Subject: [PATCH 010/356] =?UTF-8?q?[FEAT]=20Refresh=20Token=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/application/KakaoOauthService.java | 1 - .../domain/auth/application/OauthService.java | 14 +++++++++++--- .../domain/member/application/MemberService.java | 8 ++++++-- .../member/domain/repository/MemberRepository.java | 7 +++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java index 39266621..864c7e0b 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java @@ -4,7 +4,6 @@ import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/ttubeog/domain/auth/application/OauthService.java b/src/main/java/com/ttubeog/domain/auth/application/OauthService.java index 5bec71e7..1f436923 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/OauthService.java @@ -1,14 +1,11 @@ package com.ttubeog.domain.auth.application; import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.dto.MemberDto; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.Optional; - @RequiredArgsConstructor @Service public class OauthService { @@ -33,4 +30,15 @@ public String getTokens(Long id, HttpServletResponse response) { return accessToken; } + + // 리프레시 토큰을 액세스 토큰으로 갱신 + public String refreshToAccessToken(String refreshToken) { + MemberDto memberDto = memberService.findByRefreshToken(refreshToken); + + if(memberDto == null) { + + } + + return jwtTokenService.createAccessToken(memberDto.getId().toString()); + } } diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index a79ec70b..4aa7d84c 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -42,11 +42,15 @@ public ResponseEntity getCurrentUser(MemberPrincipal memberPrincipal){ } public MemberDto findById(Long id) { - Optional optionalMember = memberRepository.findById(id); + Optional member = memberRepository.findById(id); - return optionalMember.map(MemberDto::toEntity).orElse(null); + return member.map(MemberDto::toEntity).orElse(null); } + public MemberDto findByRefreshToken(String refreshToken) { + Optional member = memberRepository.findByRefreshToken(refreshToken); + return member.map(MemberDto::toEntity).orElse(null); + } public void save(MemberDto memberDetailRes) { diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 78b88eaa..c4b61a5e 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.member.domain.repository; import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.dto.MemberDto; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -8,8 +9,10 @@ @Repository public interface MemberRepository extends JpaRepository{ - + Optional findByEmail(String email); - Boolean existsByEmail(String email); + Optional findByRefreshToken(String refreshToken); + + Boolean existsByEmail(String email); } From 1fde5de7092150793a3048ba0ff7f4be9c187b74 Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 19:50:41 +0900 Subject: [PATCH 011/356] =?UTF-8?q?[FEAT]=20=ED=86=A0=ED=81=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20DTO=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/controller/OauthController.java | 4 ++++ .../com/ttubeog/domain/auth/dto/OauthRequestDto.java | 8 ++++++++ .../com/ttubeog/domain/auth/dto/OauthResponseDto.java | 10 ++++++++++ .../domain/auth/dto/RefreshTokenResponseDto.java | 11 +++++++++++ .../member/domain/repository/MemberRepository.java | 1 - 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 8d16e68b..4c2a3e91 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -1,9 +1,13 @@ package com.ttubeog.domain.auth.controller; +import com.ttubeog.domain.auth.application.OauthService; import lombok.RequiredArgsConstructor; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class OauthController { + private final OauthService oauthService; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java new file mode 100644 index 00000000..7b7ea9b0 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.auth.dto; + +import lombok.Getter; + +@Getter +public class OauthRequestDto { + private String accessToken; +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java new file mode 100644 index 00000000..c5d3ddd8 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java @@ -0,0 +1,10 @@ +package com.ttubeog.domain.auth.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class OauthResponseDto { + private String accessToken; +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java new file mode 100644 index 00000000..dfaa7798 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java @@ -0,0 +1,11 @@ +package com.ttubeog.domain.auth.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RefreshTokenResponseDto { + private String accessToken; +} diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index c4b61a5e..258d5acb 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.member.domain.repository; import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.dto.MemberDto; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; From a7d1a51f445d87d7d934e79b638b1dfadd035648 Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 20:01:01 +0900 Subject: [PATCH 012/356] =?UTF-8?q?[FEAT]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EA=B5=AC=ED=98=84=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/controller/OauthController.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 4c2a3e91..0e505a56 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -1,13 +1,30 @@ package com.ttubeog.domain.auth.controller; import com.ttubeog.domain.auth.application.OauthService; +import com.ttubeog.domain.auth.dto.OauthRequestDto; +import com.ttubeog.domain.auth.dto.OauthResponseDto; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class OauthController { private final OauthService oauthService; + + // 카카오 로그인 + @PostMapping("/auth/login/kakao") + public OauthResponseDto loginWithKaKao( + @RequestBody + OauthRequestDto oauthRequestDto, + HttpServletResponse response + ) { + OauthResponseDto oauthResponseDto = new OauthResponseDto(); + String accessToken = oauthService.loginWithKakao(oauthResponseDto.getAccessToken(), response); + oauthResponseDto.setAccessToken(accessToken); + return oauthResponseDto; + } } From 9d424b389af003cd74c4f882949c9505e8794f12 Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 17 Jan 2024 20:18:15 +0900 Subject: [PATCH 013/356] =?UTF-8?q?[FEAT]=20=ED=86=A0=ED=81=B0=EC=9D=84=20?= =?UTF-8?q?=EC=BF=A0=ED=82=A4=EC=97=90=20=EC=A0=80=EC=9E=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/JwtTokenService.java | 25 +++++++++++++++++++ .../member/presentation/MemberController.java | 8 +++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java index a35090fe..0e22724f 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java @@ -1,11 +1,14 @@ package com.ttubeog.domain.auth.application; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; import io.jsonwebtoken.security.Keys; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -70,6 +73,18 @@ public String createRefreshToken() { return createToken(newPayload, refreshTokenExpirationInSeconds); } + public String getPayload(String token) { + try { + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody() + .getSubject(); + } catch (ExpiredJwtException e) { + return e.getClaims().getSubject(); + } + } private String encodeBase64SecretKey(String secretKey) { @@ -83,4 +98,14 @@ private Key getKeyFromBase64EncodedKey(String encodedSecretKey) { return key; } + + // 클라이언트 쿠키에 리프레시 토큰을 저장 + public void addRefreshTokenToCookie(String refreshToken, HttpServletResponse response) { + Long age = refreshTokenExpirationInSeconds; + Cookie cookie = new Cookie("refresh_token", refreshToken); + cookie.setPath("/"); + cookie.setMaxAge(age.intValue()); + cookie.setHttpOnly(true); + response.addCookie(cookie); + } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index aa44a65f..d31faba5 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -26,13 +26,13 @@ public class MemberController { private final MemberService memberService; - @Operation(summary = "유저 정보 확인", description = "현재 접속된 유저정보를 확인합니다.") + @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "유저 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "유저 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @GetMapping - public ResponseEntity getCurrentUser( + public ResponseEntity getCurrentMember( @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentMember MemberPrincipal memberPrincipal ) { return memberService.getCurrentUser(memberPrincipal); From efca7d1eba71dfa046da4d03b06b8dac610c3a9f Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 08:07:00 +0900 Subject: [PATCH 014/356] =?UTF-8?q?[Chore]=20CI=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20worflows=20dir=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dummy.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/dummy.txt diff --git a/.github/workflows/dummy.txt b/.github/workflows/dummy.txt new file mode 100644 index 00000000..e69de29b From 5ead9b239c6589d1ee1bba877a544b0cc676257f Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 08:11:09 +0900 Subject: [PATCH 015/356] [Chore] Create gradle.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI를 위한 gradle.yml 생성 --- .github/workflows/gradle.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/gradle.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 00000000..0863b718 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,34 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "dev" ] + pull_request: + branches: [ "dev" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Build with Gradle + uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 + with: + arguments: build From 7ad19a47c125d9c070b9dd4c768a9f9ef20efef9 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:34:40 +0900 Subject: [PATCH 016/356] Update gradle.yml Run chmod to make gradlew executable --- .github/workflows/gradle.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 0863b718..216d5ed5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -28,6 +28,8 @@ jobs: with: java-version: '17' distribution: 'temurin' + - name: Run chmod to make gradlew executable + run: chmod +x ./gradlew - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 with: From ed76baf999f7a1f895486ad0d3dae561d592effb Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 18 Jan 2024 14:24:53 +0900 Subject: [PATCH 017/356] =?UTF-8?q?[FEAT]=20SecurityConfig=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java new file mode 100644 index 00000000..3d237ec8 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -0,0 +1,41 @@ +package com.ttubeog.domain.auth.config; + +import com.ttubeog.domain.auth.application.JwtTokenService; +import com.ttubeog.domain.member.application.MemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; + +import static org.springframework.security.config.Customizer.withDefaults; + +@RequiredArgsConstructor +@Configuration +public class SecurityConfig { + private final JwtTokenService jwtTokenService; + private final MemberService memberService; + + @Bean + public AuthenticationManager authenticationManager( + final AuthenticationConfiguration authenticationConfiguration + ) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + + @Bean + public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exception { + return httpSecurity.cors(withDefaults()) + .csrf((csrf) -> csrf.disable()) + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/auth/login/**", "/token/refresh").permitAll() + .anyRequest().authenticated()) + .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 + .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable()) // 기본 http 미사용 + .build(); + } +} From 591b448fae71ab27007d391992b93ca349399609 Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 18 Jan 2024 14:55:53 +0900 Subject: [PATCH 018/356] =?UTF-8?q?[FEAT]=20JWT=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/JwtTokenService.java | 17 +++++-- .../domain/auth/config/SecurityConfig.java | 3 ++ .../ttubeog/domain/auth/filter/JwtFilter.java | 47 +++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java diff --git a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java index 0e22724f..c9246c54 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java @@ -1,9 +1,6 @@ package com.ttubeog.domain.auth.application; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; import io.jsonwebtoken.security.Keys; @@ -86,6 +83,18 @@ public String getPayload(String token) { } } + public boolean validateToken(String token) { + try { + Jws claimsJws = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + return !claimsJws.getBody().getExpiration().before(new Date()); + } catch (JwtException | IllegalArgumentException exception) { + return false; + } + } + private String encodeBase64SecretKey(String secretKey) { return Encoders.BASE64.encode(secretKey.getBytes(StandardCharsets.UTF_8)); diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 3d237ec8..4e255c55 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.auth.config; import com.ttubeog.domain.auth.application.JwtTokenService; +import com.ttubeog.domain.auth.filter.JwtFilter; import com.ttubeog.domain.member.application.MemberService; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; @@ -10,6 +11,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import static org.springframework.security.config.Customizer.withDefaults; @@ -36,6 +38,7 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable()) // 기본 http 미사용 + .addFilterBefore(new JwtFilter(jwtTokenService, memberService), UsernamePasswordAuthenticationFilter.class) // JWT 필터 추가 .build(); } } diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java new file mode 100644 index 00000000..4a10a9b5 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -0,0 +1,47 @@ +package com.ttubeog.domain.auth.filter; + +import com.ttubeog.domain.auth.application.JwtTokenService; +import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.global.config.security.token.MemberPrincipal; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.GenericFilterBean; + +import java.io.IOException; +import java.nio.file.attribute.UserPrincipal; + +@RequiredArgsConstructor +public class JwtFilter extends GenericFilterBean { + public static final String AUTHORIZATION_HEADER = "Authorization"; + private final JwtTokenService jwtTokenService; + private final MemberService memberService; + + // 액세스 토큰이 유효한지 확인하고 SecurityContext에 계정 정보를 저장 + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); + String jwt = resolveToken(httpServletRequest); + } + + // 헤더에서 액세스 토큰 가져오는 코드 + private String resolveToken(HttpServletRequest servletRequest) { + String bearerToken = servletRequest.getHeader(AUTHORIZATION_HEADER); + + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + return bearerToken.substring(7); + } + + return null; + } +} From bb8d8babdb96d42d0d6ce9039ab95c729482d8c0 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:45:42 +0900 Subject: [PATCH 019/356] =?UTF-8?q?[Chore]=20build.gradle=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20mariaDB=20=EC=97=B0=EA=B2=B0=20->=20MySQL=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=EB=A1=9C=20build.gradle=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index eb5a9b8c..f746ce27 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' From 4c28c2b7d068ef29e2335bfc39b3ad7c3cf38aaa Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:46:33 +0900 Subject: [PATCH 020/356] =?UTF-8?q?[Chore]=20dummy.txt=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20workflows=20directory=20=EC=83=9D=EC=84=B1=EC=9D=84?= =?UTF-8?q?=20=EC=9C=84=ED=95=B4=20=EB=A7=8C=EB=93=A0=20dummy.txt=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dummy.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/dummy.txt diff --git a/.github/workflows/dummy.txt b/.github/workflows/dummy.txt deleted file mode 100644 index e69de29b..00000000 From 3f8cc3c08a8ff32ec8080ffec35d9f13dd545a56 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 18 Jan 2024 16:01:17 +0900 Subject: [PATCH 021/356] =?UTF-8?q?[Feat]=20Comment=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/domain/Comment.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java index 8a25efcc..7d0a7dd7 100644 --- a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java +++ b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java @@ -1,15 +1,38 @@ package com.ttubeog.domain.comment.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.*; +import lombok.*; @Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "comment") public class Comment extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "content") + private String content; + + @Column(name = "latitude") + private Float latitude; + + @Column(name = "longitude") + private Float longitude; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + public Comment(Long id, String content, Float latitude, Float longitude) { + this.id = id; + this.content = content; + this.latitude = latitude; + this.longitude = longitude; + } } From f93f925d2b5a669adbbeeef46539dfcee65b0564 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:42:37 +0900 Subject: [PATCH 022/356] =?UTF-8?q?[Chore]=20modify=20gradle.yml=20secret?= =?UTF-8?q?=20key=20=ED=99=98=EA=B2=BD=20=EB=B3=80=EC=88=98=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 216d5ed5..8abe4f0f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,6 +13,9 @@ on: pull_request: branches: [ "dev" ] +env: + S3_BUCKET_NAME: s3-ttubeog + permissions: contents: read @@ -23,14 +26,36 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' + + - name: Copy secret + env: + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} + OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} + OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} + OCCUPY_SWAGGER_SECRET: ${{ secrets.OCCUPY_SWAGGER_SECRET }} + OCCUPY_SECRET_DIR: src/main/resources + OCCUPY_DB_SECRET_DIR: $OCCUPY_SECRET_DIR/database + OCCUPY_OAUTH_SECRET_DIR: $OCCUPY_SECRET_DIR/oauth2 + OCCUPY_SWAGGER_SECRET_DIR: $OCCUPY_SECRET_DIR/swagger + OCCUPY_SECRET_DIR_FILE_NAME: application.yml + OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml + OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml + OCCUPY_swagger_SECRET_DIR_FILE_NAME: application-springdoc.yml + run: echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && + echo $OCCUPY_DB_SECRET | base64 --decode > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME && + echo $OCCUPY_OAUTH_SECRET | base64 --decode > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME && + echo $OCCUPY_SWAGGER_SECRET | base64 --decode > $OCCUPY_SWAGGER_SECRET_DIR/$OCCUPY_SWAGGER_SECRET_DIR_FILE_NAME + - name: Run chmod to make gradlew executable run: chmod +x ./gradlew + - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 with: - arguments: build + arguments: build \ No newline at end of file From f1f10da61ee500b1ce096685a4ec2f8d22bec2ed Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:50:20 +0900 Subject: [PATCH 023/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 8abe4f0f..6f223311 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,8 +13,6 @@ on: pull_request: branches: [ "dev" ] -env: - S3_BUCKET_NAME: s3-ttubeog permissions: contents: read From f55ff3851daa4cb7c421a3ace0345d15c008ca54 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:51:07 +0900 Subject: [PATCH 024/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 6f223311..e7dee891 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -45,7 +45,8 @@ jobs: OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml OCCUPY_swagger_SECRET_DIR_FILE_NAME: application-springdoc.yml - run: echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && + run: + echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && echo $OCCUPY_DB_SECRET | base64 --decode > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME && echo $OCCUPY_OAUTH_SECRET | base64 --decode > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME && echo $OCCUPY_SWAGGER_SECRET | base64 --decode > $OCCUPY_SWAGGER_SECRET_DIR/$OCCUPY_SWAGGER_SECRET_DIR_FILE_NAME From 495b03d90b4e2be907b3ac5d7111efd1971f245e Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 18 Jan 2024 17:35:04 +0900 Subject: [PATCH 025/356] =?UTF-8?q?[Chore]=20gitignore=20=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resources 전체 무시 -> database.yml, oauth2.yml만 무시 --- .gitignore | 3 ++- src/main/resources/application.yml | 27 +++++++++++++++++++ .../swagger/application-springdoc.yml | 14 ++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/swagger/application-springdoc.yml diff --git a/.gitignore b/.gitignore index 81655f97..5ab638fc 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,8 @@ out/ .LSOverride ### Project security ### -**/resources/ +/src/main/resources/database/ +/src/main/resources/oauth2/ Dockerfile docker-compose.yaml deploy_*.sh diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 00000000..c311394b --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,27 @@ +# logging 설정 +logging: + level: + org: + hibernate: + type: + descriptor: + sql: debug + +# console 색상 +spring: + output: + ansi: + enabled: always + mvc: + pathmatch: + matching-strategy: ant_path_matcher + + +# 오류 처리 +server: + error: + include-exception: true + include-stacktrace: always + + #port 설정 + port: 8080 \ No newline at end of file diff --git a/src/main/resources/swagger/application-springdoc.yml b/src/main/resources/swagger/application-springdoc.yml new file mode 100644 index 00000000..59bfb544 --- /dev/null +++ b/src/main/resources/swagger/application-springdoc.yml @@ -0,0 +1,14 @@ +springdoc: + default-consumes-media-type: application/json;charset=UTF-8 + default-produces-media-type: application/json;charset=UTF-8 + swagger-ui: + path: swagger + disable-swagger-default-url: true + display-request-duration: true + operations-sorter: method + doc-expansion: none + + # enabled: false + # query-config-enabled: false + # api-docs: + # enabled: false \ No newline at end of file From 915760d69dda3ff6b2d8ff5f020ec6100cc795e5 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 18 Jan 2024 17:42:21 +0900 Subject: [PATCH 026/356] =?UTF-8?q?[Feat]=20Comment=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 49 +++++++++++++++++++ .../domain/comment/domain/Comment.java | 10 +--- .../comment/dto/request/CommentWriteReq.java | 16 ++++++ .../comment/dto/response/CommentWriteRes.java | 33 +++++++++++++ .../presentation/CommentController.java | 38 ++++++++++++++ 5 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 76ea8a0b..c049bd7b 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -1,11 +1,60 @@ package com.ttubeog.domain.comment.application; +import com.ttubeog.domain.comment.domain.Comment; +import com.ttubeog.domain.comment.domain.repository.CommentRepository; +import com.ttubeog.domain.comment.dto.request.CommentWriteReq; +import com.ttubeog.domain.comment.dto.response.CommentWriteRes; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.global.DefaultAssert; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) public class CommentService { + + private final CommentRepository commentRepository; + private final MemberRepository memberRepository; + + // 댓글 작성 + @Transactional + public ResponseEntity writeComment(UserPrincipal userPrincipal, CommentWriteReq commentWriteReq) { + + Optional optionalMember = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(optionalMember); + Member member = optionalMember.get(); + + Comment comment = Comment.builder() + .content(commentWriteReq.getContent()) + .latitude(commentWriteReq.getLatitude()) + .longitude(commentWriteReq.getLongitude()) + .member(member) + .build(); + + commentRepository.save(comment); + + CommentWriteRes commentWriteRes = CommentWriteRes.builder() + .commentId(comment.getId()) + .memberId(member.getId()) + .content(comment.getContent()) + .latitude(comment.getLatitude()) + .longitude(comment.getLongitude()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(commentWriteRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java index 7d0a7dd7..f83a073c 100644 --- a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java +++ b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java @@ -7,7 +7,9 @@ @Entity @Getter +@Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor @Table(name = "comment") public class Comment extends BaseEntity { @@ -27,12 +29,4 @@ public class Comment extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; - - @Builder - public Comment(Long id, String content, Float latitude, Float longitude) { - this.id = id; - this.content = content; - this.latitude = latitude; - this.longitude = longitude; - } } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java new file mode 100644 index 00000000..2987795a --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java @@ -0,0 +1,16 @@ +package com.ttubeog.domain.comment.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "댓글 작성 Request") +public class CommentWriteReq { + + @Schema(description = "댓글 내용") + private String content; + @Schema(description = "위도") + private Float latitude; + @Schema(description = "경도") + private Float longitude; +} diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java new file mode 100644 index 00000000..6c62b592 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java @@ -0,0 +1,33 @@ +package com.ttubeog.domain.comment.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class CommentWriteRes { + + @Schema(description = "댓글 ID") + private Long commentId; + + @Schema(description = "작성자 ID") + private Long memberId; + + @Schema(description = "내용") + private String content; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Builder + public CommentWriteRes(Long commentId, Long memberId, String content, Float latitude, Float longitude) { + this.commentId = commentId; + this.memberId = memberId; + this.content = content; + this.latitude = latitude; + this.longitude = longitude; + } +} diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index b2f17b3f..76a91abd 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -1,7 +1,45 @@ package com.ttubeog.domain.comment.presentation; +import com.ttubeog.domain.comment.application.CommentService; +import com.ttubeog.domain.comment.dto.request.CommentWriteReq; +import com.ttubeog.domain.comment.dto.response.CommentWriteRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ErrorResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "Comment", description = "Comment API") @RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/comment") public class CommentController { + + private final CommentService commentService; + @Operation(summary = "댓글 작성", description = "댓글을 작성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommentWriteRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + }) + @PostMapping + public ResponseEntity writeComment( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CommentWriteReq commentWriteReq + ) { + return commentService.writeComment(userPrincipal, commentWriteReq); + } + + } From 723143a5ee98e91ff4ebb21d0375159806157121 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 18 Jan 2024 18:43:23 +0900 Subject: [PATCH 027/356] =?UTF-8?q?[Feat]=20Comment=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 32 +++++++++++++++++++ .../domain/comment/domain/Comment.java | 4 +++ .../comment/dto/request/CommentUpdateReq.java | 14 ++++++++ .../dto/response/CommentUpdateRes.java | 21 ++++++++++++ .../presentation/CommentController.java | 25 ++++++++++++--- 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index c049bd7b..af2def9f 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -2,12 +2,15 @@ import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; +import com.ttubeog.domain.comment.dto.request.CommentUpdateReq; import com.ttubeog.domain.comment.dto.request.CommentWriteReq; +import com.ttubeog.domain.comment.dto.response.CommentUpdateRes; import com.ttubeog.domain.comment.dto.response.CommentWriteRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.error.DefaultException; import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -57,4 +60,33 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, CommentWriteR return ResponseEntity.ok(apiResponse); } + // 댓글 수정 + @Transactional + public ResponseEntity updateComment(UserPrincipal userPrincipal, CommentUpdateReq commentUpdateReq) { + + Optional optionalMember = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(optionalMember); + + Optional optionalComment = commentRepository.findById(commentUpdateReq.getCommentId()); + DefaultAssert.isOptionalPresent(optionalComment); + Comment comment = optionalComment.get(); + + Member commentWriter = comment.getMember(); + if (commentWriter.getId() != optionalMember.get().getId()) { + DefaultAssert.isTrue(true, "해당 댓글의 작성자만 수정할 수 있습니다."); + } + + comment.updateContent(commentUpdateReq.getContent()); + CommentUpdateRes commentUpdateRes = CommentUpdateRes.builder() + .commentId(comment.getId()) + .content(comment.getContent()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(commentUpdateRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java index f83a073c..6d4f8c01 100644 --- a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java +++ b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java @@ -29,4 +29,8 @@ public class Comment extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; + + public void updateContent(String content) { + this.content = content; + } } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java new file mode 100644 index 00000000..95e1fdef --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.comment.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class CommentUpdateReq { + + @Schema(description = "댓글 ID") + private Long commentId; + + @Schema(description = "댓글 내용") + private String content; +} diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java new file mode 100644 index 00000000..30e95954 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java @@ -0,0 +1,21 @@ +package com.ttubeog.domain.comment.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class CommentUpdateRes { + + @Schema(description = "댓글 ID") + private Long commentId; + + @Schema(description = "내용") + private String content; + + @Builder + public CommentUpdateRes(Long commentId, String content) { + this.commentId = commentId; + this.content = content; + } +} diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index 76a91abd..6408ebfd 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.comment.presentation; import com.ttubeog.domain.comment.application.CommentService; +import com.ttubeog.domain.comment.dto.request.CommentUpdateReq; import com.ttubeog.domain.comment.dto.request.CommentWriteReq; +import com.ttubeog.domain.comment.dto.response.CommentUpdateRes; import com.ttubeog.domain.comment.dto.response.CommentWriteRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -16,10 +18,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "Comment", description = "Comment API") @RestController @@ -28,6 +27,8 @@ public class CommentController { private final CommentService commentService; + + // 댓글 작성 @Operation(summary = "댓글 작성", description = "댓글을 작성합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommentWriteRes.class) ) } ), @@ -41,5 +42,21 @@ public ResponseEntity writeComment( return commentService.writeComment(userPrincipal, commentWriteReq); } + // 댓글 수정 + @Operation(summary = "댓글 수정", description = "댓글 내용을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommentUpdateRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + }) + @PatchMapping + public ResponseEntity updateComment( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CommentUpdateReq commentUpdateReq + ) { + return commentService.updateComment(userPrincipal, commentUpdateReq); + } + + // 댓글 삭제 + } From b046e88d50113365d1eaa57dcb41e64d0d12067f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 18 Jan 2024 18:54:25 +0900 Subject: [PATCH 028/356] =?UTF-8?q?[Feat]=20Comment=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 22 +++++++++++++++++++ .../presentation/CommentController.java | 15 +++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index af2def9f..708c1859 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -12,6 +12,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.error.DefaultException; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -89,4 +90,25 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, CommentUpdat return ResponseEntity.ok(apiResponse); } + + // 댓글 삭제 + @Transactional + public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { + + Optional optionalMember = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(optionalMember); + + Optional optionalComment = commentRepository.findById(commentId); + DefaultAssert.isOptionalPresent(optionalComment); + Comment comment = optionalComment.get(); + + commentRepository.delete(comment); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("댓글이 정상적으로 삭제되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index 6408ebfd..a3b1e758 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -8,6 +8,7 @@ import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -57,6 +58,16 @@ public ResponseEntity updateComment( } // 댓글 삭제 - - + @Operation(summary = "댓글 삭제", description = "댓글을 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + }) + @DeleteMapping("/{commentId}") + public ResponseEntity deleteComment( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @PathVariable Long commentId + ) { + return commentService.deleteComment(userPrincipal, commentId); + } } From 68dc9745c8ab97e6324975b32d339f0273bad1f1 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 19 Jan 2024 11:31:33 +0900 Subject: [PATCH 029/356] =?UTF-8?q?[Chore]=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 60 ++++++++++--------- ...ntUpdateReq.java => UpdateCommentReq.java} | 2 +- ...mentWriteReq.java => WriteCommentReq.java} | 2 +- ...ntUpdateRes.java => UpdateCommentRes.java} | 4 +- ...mentWriteRes.java => WriteCommentRes.java} | 4 +- .../presentation/CommentController.java | 22 +++---- 6 files changed, 49 insertions(+), 45 deletions(-) rename src/main/java/com/ttubeog/domain/comment/dto/request/{CommentUpdateReq.java => UpdateCommentReq.java} (89%) rename src/main/java/com/ttubeog/domain/comment/dto/request/{CommentWriteReq.java => WriteCommentReq.java} (92%) rename src/main/java/com/ttubeog/domain/comment/dto/response/{CommentUpdateRes.java => UpdateCommentRes.java} (79%) rename src/main/java/com/ttubeog/domain/comment/dto/response/{CommentWriteRes.java => WriteCommentRes.java} (88%) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 708c1859..367e2fef 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -2,15 +2,14 @@ import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; -import com.ttubeog.domain.comment.dto.request.CommentUpdateReq; -import com.ttubeog.domain.comment.dto.request.CommentWriteReq; -import com.ttubeog.domain.comment.dto.response.CommentUpdateRes; -import com.ttubeog.domain.comment.dto.response.CommentWriteRes; +import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; +import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; +import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; -import com.ttubeog.global.error.DefaultException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; @@ -30,22 +29,22 @@ public class CommentService { // 댓글 작성 @Transactional - public ResponseEntity writeComment(UserPrincipal userPrincipal, CommentWriteReq commentWriteReq) { + public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentReq writeCommentReq) { - Optional optionalMember = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(optionalMember); - Member member = optionalMember.get(); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); + Member member = memberOptional.get(); Comment comment = Comment.builder() - .content(commentWriteReq.getContent()) - .latitude(commentWriteReq.getLatitude()) - .longitude(commentWriteReq.getLongitude()) + .content(writeCommentReq.getContent()) + .latitude(writeCommentReq.getLatitude()) + .longitude(writeCommentReq.getLongitude()) .member(member) .build(); commentRepository.save(comment); - CommentWriteRes commentWriteRes = CommentWriteRes.builder() + WriteCommentRes writeCommentRes = WriteCommentRes.builder() .commentId(comment.getId()) .memberId(member.getId()) .content(comment.getContent()) @@ -55,7 +54,7 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, CommentWriteR ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(commentWriteRes) + .information(writeCommentRes) .build(); return ResponseEntity.ok(apiResponse); @@ -63,29 +62,29 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, CommentWriteR // 댓글 수정 @Transactional - public ResponseEntity updateComment(UserPrincipal userPrincipal, CommentUpdateReq commentUpdateReq) { + public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommentReq updateCommentReq) { - Optional optionalMember = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(optionalMember); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); - Optional optionalComment = commentRepository.findById(commentUpdateReq.getCommentId()); - DefaultAssert.isOptionalPresent(optionalComment); - Comment comment = optionalComment.get(); + Optional commentOptional = commentRepository.findById(updateCommentReq.getCommentId()); + DefaultAssert.isOptionalPresent(commentOptional); + Comment comment = commentOptional.get(); Member commentWriter = comment.getMember(); - if (commentWriter.getId() != optionalMember.get().getId()) { + if (commentWriter.getId() != memberOptional.get().getId()) { DefaultAssert.isTrue(true, "해당 댓글의 작성자만 수정할 수 있습니다."); } - comment.updateContent(commentUpdateReq.getContent()); - CommentUpdateRes commentUpdateRes = CommentUpdateRes.builder() + comment.updateContent(updateCommentReq.getContent()); + UpdateCommentRes updateCommentRes = UpdateCommentRes.builder() .commentId(comment.getId()) .content(comment.getContent()) .build(); ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(commentUpdateRes) + .information(updateCommentRes) .build(); return ResponseEntity.ok(apiResponse); @@ -95,12 +94,12 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, CommentUpdat @Transactional public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { - Optional optionalMember = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(optionalMember); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); - Optional optionalComment = commentRepository.findById(commentId); - DefaultAssert.isOptionalPresent(optionalComment); - Comment comment = optionalComment.get(); + Optional commentOptional = commentRepository.findById(commentId); + DefaultAssert.isOptionalPresent(commentOptional); + Comment comment = commentOptional.get(); commentRepository.delete(comment); @@ -111,4 +110,7 @@ public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long comment return ResponseEntity.ok(apiResponse); } + + // 댓글 조회 + } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/UpdateCommentReq.java similarity index 89% rename from src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java rename to src/main/java/com/ttubeog/domain/comment/dto/request/UpdateCommentReq.java index 95e1fdef..2f3a39ab 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentUpdateReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/UpdateCommentReq.java @@ -4,7 +4,7 @@ import lombok.Data; @Data -public class CommentUpdateReq { +public class UpdateCommentReq { @Schema(description = "댓글 ID") private Long commentId; diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java similarity index 92% rename from src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java rename to src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java index 2987795a..d0541d7f 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/CommentWriteReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java @@ -5,7 +5,7 @@ @Data @Schema(description = "댓글 작성 Request") -public class CommentWriteReq { +public class WriteCommentReq { @Schema(description = "댓글 내용") private String content; diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/UpdateCommentRes.java similarity index 79% rename from src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java rename to src/main/java/com/ttubeog/domain/comment/dto/response/UpdateCommentRes.java index 30e95954..7fafb00c 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentUpdateRes.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/UpdateCommentRes.java @@ -5,7 +5,7 @@ import lombok.Data; @Data -public class CommentUpdateRes { +public class UpdateCommentRes { @Schema(description = "댓글 ID") private Long commentId; @@ -14,7 +14,7 @@ public class CommentUpdateRes { private String content; @Builder - public CommentUpdateRes(Long commentId, String content) { + public UpdateCommentRes(Long commentId, String content) { this.commentId = commentId; this.content = content; } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java similarity index 88% rename from src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java rename to src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java index 6c62b592..a3b78a19 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/response/CommentWriteRes.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java @@ -5,7 +5,7 @@ import lombok.Data; @Data -public class CommentWriteRes { +public class WriteCommentRes { @Schema(description = "댓글 ID") private Long commentId; @@ -23,7 +23,7 @@ public class CommentWriteRes { private Float longitude; @Builder - public CommentWriteRes(Long commentId, Long memberId, String content, Float latitude, Float longitude) { + public WriteCommentRes(Long commentId, Long memberId, String content, Float latitude, Float longitude) { this.commentId = commentId; this.memberId = memberId; this.content = content; diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index a3b1e758..cfd84fef 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -1,10 +1,10 @@ package com.ttubeog.domain.comment.presentation; import com.ttubeog.domain.comment.application.CommentService; -import com.ttubeog.domain.comment.dto.request.CommentUpdateReq; -import com.ttubeog.domain.comment.dto.request.CommentWriteReq; -import com.ttubeog.domain.comment.dto.response.CommentUpdateRes; -import com.ttubeog.domain.comment.dto.response.CommentWriteRes; +import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; +import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; +import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -32,29 +32,29 @@ public class CommentController { // 댓글 작성 @Operation(summary = "댓글 작성", description = "댓글을 작성합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommentWriteRes.class) ) } ), + @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = WriteCommentRes.class) ) } ), @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) }) @PostMapping public ResponseEntity writeComment( @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody CommentWriteReq commentWriteReq + @Valid @RequestBody WriteCommentReq writeCommentReq ) { - return commentService.writeComment(userPrincipal, commentWriteReq); + return commentService.writeComment(userPrincipal, writeCommentReq); } // 댓글 수정 @Operation(summary = "댓글 수정", description = "댓글 내용을 수정합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommentUpdateRes.class) ) } ), + @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateCommentRes.class) ) } ), @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) }) @PatchMapping public ResponseEntity updateComment( @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody CommentUpdateReq commentUpdateReq + @Valid @RequestBody UpdateCommentReq updateCommentReq ) { - return commentService.updateComment(userPrincipal, commentUpdateReq); + return commentService.updateComment(userPrincipal, updateCommentReq); } // 댓글 삭제 @@ -70,4 +70,6 @@ public ResponseEntity deleteComment( ) { return commentService.deleteComment(userPrincipal, commentId); } + + // 댓글 조회 } From 3a36fffb85cf682833f6fc731af3fb8159203cd2 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 11:57:15 +0900 Subject: [PATCH 030/356] =?UTF-8?q?[Feat]=20MemberBenefit=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Member와 Benefit을 연결하는 테이블을 초기 설정했습니다. --- .../domain/benefit/domain/MemberBenefit.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java new file mode 100644 index 00000000..569b1b64 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java @@ -0,0 +1,40 @@ +package com.ttubeog.domain.benefit.domain; + +import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class MemberBenefit extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "benefit_id") + private Benefit benefit; + + private Boolean is_used = false; // 사용 여부 + + private Boolean has_expired = false; // 만료 여부 + + @Builder + public MemberBenefit(Long id, Member member, Benefit benefit, Boolean is_used, Boolean has_expired) { + this.id = id; + this.member = member; + this.benefit = benefit; + this.is_used = is_used; + this.has_expired = has_expired; + } +} From c430078cd9bc9a921bf793e9c1e30bf78cf95e1c Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 12:00:15 +0900 Subject: [PATCH 031/356] =?UTF-8?q?[Feat]=20MemberBenefitRepository=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Repository 파일을 만들었습니다. --- .../domain/repository/MemberBenefitRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java new file mode 100644 index 00000000..fd7f904c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.benefit.domain.repository; + +import com.ttubeog.domain.benefit.domain.MemberBenefit; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MemberBenefitRepository extends JpaRepository { +} From ababa7cebeaddffa101f9ddeafb6891257a99f7b Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 12:15:31 +0900 Subject: [PATCH 032/356] =?UTF-8?q?[Chore]=20optional=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit userOptional -> memberOptional --- .../domain/benefit/application/BenefitService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 489e7550..9f39565f 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; @@ -70,8 +71,8 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi @Transactional public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - Optional userOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(userOptional); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); Optional benefitOptional = benefitRepository.findById(benefitId); DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); @@ -91,8 +92,8 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit @Transactional public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { - Optional userOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(userOptional); + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); Optional benefitOptional = benefitRepository.findById(updateBenefitReq.getBenefitId()); DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); From 57fb0e6f1145e4892ee71883fa33d87286f75a78 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 19 Jan 2024 14:29:22 +0900 Subject: [PATCH 033/356] =?UTF-8?q?[FIX]=20=EB=B9=8C=EB=93=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../CustomDefaultOAuth2UserService.java | 148 ++++++------- .../CustomMemberDetailsService.java | 6 +- .../CustomTokenProviderService.java | 14 +- ...yConfig.java => SecurityDomainConfig.java} | 4 +- .../ttubeog/domain/auth/filter/JwtFilter.java | 7 - .../member/application/MemberService.java | 6 +- .../ttubeog/domain/member/domain/Member.java | 13 +- .../domain/member/domain/Provider.java | 4 +- .../member/presentation/MemberController.java | 8 +- .../config/security/SecurityConfig.java | 198 +++++++++--------- .../config/security/auth/OAuth2UserInfo.java | 2 + .../security/auth/OAuth2UserInfoFactory.java | 58 ++--- .../config/security/auth/company/Kakao.java | 111 +++++----- .../{CurrentMember.java => CurrentUser.java} | 2 +- ...emberPrincipal.java => UserPrincipal.java} | 16 +- 16 files changed, 301 insertions(+), 297 deletions(-) rename src/main/java/com/ttubeog/domain/auth/config/{SecurityConfig.java => SecurityDomainConfig.java} (97%) rename src/main/java/com/ttubeog/global/config/security/token/{CurrentMember.java => CurrentUser.java} (89%) rename src/main/java/com/ttubeog/global/config/security/token/{MemberPrincipal.java => UserPrincipal.java} (80%) diff --git a/build.gradle b/build.gradle index 1f331e96..c241d2db 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,7 @@ dependencies { annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" runtimeOnly 'com.mysql:mysql-connector-j' + implementation 'org.mariadb.jdbc:mariadb-java-client:2.6.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java index 5e7d7577..d6891f08 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java @@ -1,74 +1,74 @@ -package com.ttubeog.domain.auth.application; - -import com.ttubeog.domain.member.domain.Provider; -import com.ttubeog.domain.member.domain.Role; -import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.domain.repository.MemberRepository; -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.auth.OAuth2UserInfo; -import com.ttubeog.global.config.security.auth.OAuth2UserInfoFactory; -import com.ttubeog.global.config.security.token.MemberPrincipal; -import lombok.RequiredArgsConstructor; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@RequiredArgsConstructor -@Service -public class CustomDefaultOAuth2UserService extends DefaultOAuth2UserService{ - - private final MemberRepository memberRepository; - - @Override - public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException { - OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest); - try { - return processOAuth2User(oAuth2UserRequest, oAuth2User); - } catch (Exception e) { - DefaultAssert.isAuthentication(e.getMessage()); - } - return null; - } - - private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); - DefaultAssert.isAuthentication(!oAuth2UserInfo.getEmail().isEmpty()); - - Optional userOptional = memberRepository.findByEmail(oAuth2UserInfo.getEmail()); - Member member; - if(userOptional.isPresent()) { - member = userOptional.get(); - DefaultAssert.isAuthentication(member.getProvider().equals(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))); - member = updateExistingMember(member, oAuth2UserInfo); - } else { - member = registerNewMember(oAuth2UserRequest, oAuth2UserInfo); - } - - return MemberPrincipal.create(member, oAuth2User.getAttributes()); - } - - private Member registerNewMember(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { - Member member = Member.builder() - .provider(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())) - .providerId(oAuth2UserInfo.getId()) - .name(oAuth2UserInfo.getName()) - .email(oAuth2UserInfo.getEmail()) - .imageUrl(oAuth2UserInfo.getImageUrl()) - .role(Role.USER) - .build(); - - return memberRepository.save(member); - } - - private Member updateExistingMember(Member member, OAuth2UserInfo oAuth2UserInfo) { - - member.updateName(oAuth2UserInfo.getName()); - member.updateImageUrl(oAuth2UserInfo.getImageUrl()); - - return memberRepository.save(member); - } -} +//package com.ttubeog.domain.auth.application; +// +//import com.ttubeog.domain.member.domain.Provider; +//import com.ttubeog.domain.member.domain.Role; +//import com.ttubeog.domain.member.domain.Member; +//import com.ttubeog.domain.member.domain.repository.MemberRepository; +//import com.ttubeog.global.DefaultAssert; +//import com.ttubeog.global.config.security.auth.OAuth2UserInfo; +//import com.ttubeog.global.config.security.token.UserPrincipal; +//import lombok.RequiredArgsConstructor; +//import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +//import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +//import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +//import org.springframework.security.oauth2.core.user.OAuth2User; +//import org.springframework.stereotype.Service; +// +//import java.util.Optional; +// +//@RequiredArgsConstructor +//@Service +//public class CustomDefaultOAuth2UserService extends DefaultOAuth2UserService { +// +// private final MemberRepository memberRepository; +// +// @Override +// public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException { +// OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest); +// try { +// return processOAuth2User(oAuth2UserRequest, oAuth2User); +// } catch (Exception e) { +// DefaultAssert.isAuthentication(e.getMessage()); +// } +// return null; +// } +// +// private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { +// OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); +// DefaultAssert.isAuthentication(!oAuth2UserInfo.getEmail().isEmpty()); +// +// Optional userOptional = memberRepository.findByEmail(oAuth2UserInfo.getEmail()); +// Member member; +// if (userOptional.isPresent()) { +// member = userOptional.get(); +// DefaultAssert.isAuthentication(member.getProvider().equals(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))); +// member = updateExistingMember(member, oAuth2UserInfo); +// } else { +// member = registerNewMember(oAuth2UserRequest, oAuth2UserInfo); +// } +// +// return UserPrincipal.create(member, oAuth2User.getAttributes()); +// } +// +// private Member registerNewMember(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { +// Member member = Member.builder() +// .provider(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())) +// .providerId(oAuth2UserInfo.getId()) +// .name(oAuth2UserInfo.getName()) +// .email(oAuth2UserInfo.getEmail()) +// .imageUrl(oAuth2UserInfo.getImageUrl()) +// .refreshToken(oAuth2UserInfo.getRefreshToken()) +// .role(Role.USER) +// .build(); +// +// return memberRepository.save(member); +// } +// +// private Member updateExistingMember(Member member, OAuth2UserInfo oAuth2UserInfo) { +// +// member.updateName(oAuth2UserInfo.getName()); +// member.updateImageUrl(oAuth2UserInfo.getImageUrl()); +// +// return memberRepository.save(member); +// } +//} diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java index a8b63c67..cb94a0c1 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java @@ -3,7 +3,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.MemberPrincipal; +import com.ttubeog.global.config.security.token.UserPrincipal; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; @@ -27,7 +27,7 @@ public UserDetails loadUserByUsername(String email) throws UsernameNotFoundExcep new UsernameNotFoundException("멤버 정보를 찾을 수 없습니다.") ); - return MemberPrincipal.create(member); + return UserPrincipal.create(member); } @Transactional @@ -35,7 +35,7 @@ public UserDetails loadUserById(Long id) { Optional user = memberRepository.findById(id); DefaultAssert.isOptionalPresent(user); - return MemberPrincipal.create(user.get()); + return UserPrincipal.create(user.get()); } } diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java index a6672c38..2b56e6c3 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java @@ -2,7 +2,7 @@ import com.ttubeog.domain.auth.dto.TokenMapping; import com.ttubeog.global.config.security.OAuth2Config; -import com.ttubeog.global.config.security.token.MemberPrincipal; +import com.ttubeog.global.config.security.token.UserPrincipal; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; @@ -27,7 +27,7 @@ public class CustomTokenProviderService { private CustomMemberDetailsService customMemberDetailsService; public TokenMapping refreshToken(Authentication authentication, String refreshToken) { - MemberPrincipal memberPrincipal = (MemberPrincipal) authentication.getPrincipal(); + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); Date now = new Date(); Date accessTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getAccessTokenExpirationMsec()); @@ -37,21 +37,21 @@ public TokenMapping refreshToken(Authentication authentication, String refreshTo Key key = Keys.hmacShaKeyFor(keyBytes); String accessToken = Jwts.builder() - .setSubject(Long.toString(memberPrincipal.getId())) + .setSubject(Long.toString(userPrincipal.getId())) .setIssuedAt(new Date()) .setExpiration(accessTokenExpiresIn) .signWith(key, SignatureAlgorithm.HS512) .compact(); return TokenMapping.builder() - .userEmail(memberPrincipal.getEmail()) + .userEmail(userPrincipal.getEmail()) .accessToken(accessToken) .refreshToken(refreshToken) .build(); } public TokenMapping createToken(Authentication authentication) { - MemberPrincipal memberPrincipal = (MemberPrincipal) authentication.getPrincipal(); + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); Date now = new Date(); @@ -64,7 +64,7 @@ public TokenMapping createToken(Authentication authentication) { Key key = Keys.hmacShaKeyFor(keyBytes); String accessToken = Jwts.builder() - .setSubject(Long.toString(memberPrincipal.getId())) + .setSubject(Long.toString(userPrincipal.getId())) .setIssuedAt(new Date()) .setExpiration(accessTokenExpiresIn) .signWith(key, SignatureAlgorithm.HS512) @@ -76,7 +76,7 @@ public TokenMapping createToken(Authentication authentication) { .compact(); return TokenMapping.builder() - .userEmail(memberPrincipal.getEmail()) + .userEmail(userPrincipal.getEmail()) .accessToken(accessToken) .refreshToken(refreshToken) .build(); diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java similarity index 97% rename from src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java rename to src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java index 4e255c55..e4b60c46 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java @@ -17,11 +17,11 @@ @RequiredArgsConstructor @Configuration -public class SecurityConfig { +public class SecurityDomainConfig { private final JwtTokenService jwtTokenService; private final MemberService memberService; - @Bean + @Bean(name = "domainAuth") public AuthenticationManager authenticationManager( final AuthenticationConfiguration authenticationConfiguration ) throws Exception { diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 4a10a9b5..2b5fcaed 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -2,23 +2,16 @@ import com.ttubeog.domain.auth.application.JwtTokenService; import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.global.config.security.token.MemberPrincipal; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.StringUtils; import org.springframework.web.filter.GenericFilterBean; import java.io.IOException; -import java.nio.file.attribute.UserPrincipal; @RequiredArgsConstructor public class JwtFilter extends GenericFilterBean { diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 4aa7d84c..baf6cee7 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -5,7 +5,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.MemberPrincipal; +import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -21,8 +21,8 @@ public class MemberService { private final MemberRepository memberRepository; // 현재 유저 조회 - public ResponseEntity getCurrentUser(MemberPrincipal memberPrincipal){ - Optional checkUser = memberRepository.findById(memberPrincipal.getId()); + public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ + Optional checkUser = memberRepository.findById(userPrincipal.getId()); DefaultAssert.isOptionalPresent(checkUser); Member member = checkUser.get(); diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index da6b439e..5f0cde49 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -13,7 +13,8 @@ @Getter public class Member extends BaseEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @@ -34,9 +35,10 @@ public class Member extends BaseEntity { private String providerId; private String platform; + private String refreshToken; @Builder - public Member(Long id, String name, String email, String imageUrl, Boolean emailVerified, String password, Provider provider, Role role, String providerId, String platform) { + public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, Role role, String providerId, String platform, String refreshToken) { this.id = id; this.name = name; this.email = email; @@ -46,13 +48,16 @@ public Member(Long id, String name, String email, String imageUrl, Boolean email this.role = role; this.providerId = providerId; this.platform = platform; + this.refreshToken = refreshToken; } - public void updateName(String name){ + + + public void updateName(String name) { this.name = name; } - public void updateImageUrl(String imageUrl){ + public void updateImageUrl(String imageUrl) { this.imageUrl = imageUrl; } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/Provider.java b/src/main/java/com/ttubeog/domain/member/domain/Provider.java index 05baafc4..adf6227d 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Provider.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Provider.java @@ -1,6 +1,6 @@ package com.ttubeog.domain.member.domain; public enum Provider { - kakao, - apple + KAKAO, + APPLE } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index d31faba5..7470281d 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -2,8 +2,8 @@ import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.global.config.security.token.CurrentMember; -import com.ttubeog.global.config.security.token.MemberPrincipal; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -33,9 +33,9 @@ public class MemberController { }) @GetMapping public ResponseEntity getCurrentMember( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentMember MemberPrincipal memberPrincipal + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal ) { - return memberService.getCurrentUser(memberPrincipal); + return memberService.getCurrentUser(userPrincipal); } } diff --git a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java b/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java index a26ab307..f867fee3 100644 --- a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java +++ b/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java @@ -1,99 +1,99 @@ -package com.ttubeog.global.config.security; - -import com.ttubeog.domain.auth.application.CustomDefaultOAuth2UserService; -import com.ttubeog.domain.auth.application.CustomMemberDetailsService; -import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; -import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationFailureHandler; -import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationSuccessHandler; -import com.ttubeog.global.config.security.token.CustomAuthenticationEntryPoint; -import com.ttubeog.global.config.security.token.CustomOncePerRequestFilter; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -import static org.springframework.security.config.Customizer.withDefaults; - - -@RequiredArgsConstructor -@Configuration -@EnableWebSecurity -public class SecurityConfig { - - private final CustomMemberDetailsService customMemberDetailsService; - private final CustomDefaultOAuth2UserService customOAuth2UserService; - private final CustomSimpleUrlAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; - private final CustomSimpleUrlAuthenticationFailureHandler oAuth2AuthenticationFailureHandler; - private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public CustomOncePerRequestFilter customOncePerRequestFilter() { - return new CustomOncePerRequestFilter(); - } - - @Bean - public DaoAuthenticationProvider authenticationProvider() { - DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - - authenticationProvider.setUserDetailsService(customMemberDetailsService); - authenticationProvider.setPasswordEncoder(passwordEncoder()); - - return authenticationProvider; - } - - @Bean - public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { - return authenticationConfiguration.getAuthenticationManager(); - } - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http - .cors(withDefaults()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .csrf(AbstractHttpConfigurer::disable) - .formLogin(AbstractHttpConfigurer::disable) - .httpBasic(AbstractHttpConfigurer::disable) - .exceptionHandling(exception -> exception.authenticationEntryPoint(new CustomAuthenticationEntryPoint())) - .authorizeHttpRequests(authorize -> authorize - .requestMatchers("/", "/error", "/favicon.ico", "/**/*.png", "/**/*.gif", "/**/*.svg", "/**/*.jpg", "/**/*.html", "/**/*.css", "/**/*.js") - .permitAll() - .requestMatchers("/swagger", "/swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**", "/v3/api-docs/**") - .permitAll() - .requestMatchers("/login/**","/auth/**", "/oauth2/**") - .permitAll() - .requestMatchers("/blog/**") - .permitAll() - .anyRequest() - .authenticated()) - .oauth2Login(oauth2 -> oauth2 - .authorizationEndpoint(authorization -> authorization - .baseUri("/oauth2/authorize") - .authorizationRequestRepository(customAuthorizationRequestRepository)) - .redirectionEndpoint(redirection -> redirection - .baseUri("/oauth2/callback/**")) - .userInfoEndpoint(userInfo -> userInfo - .userService(customOAuth2UserService)) - .successHandler(oAuth2AuthenticationSuccessHandler) - .failureHandler(oAuth2AuthenticationFailureHandler)); - - http.addFilterBefore(customOncePerRequestFilter(), UsernamePasswordAuthenticationFilter.class); - return http.build(); - } - -} +//package com.ttubeog.global.config.security; +// +//import com.ttubeog.domain.auth.application.CustomDefaultOAuth2UserService; +//import com.ttubeog.domain.auth.application.CustomMemberDetailsService; +//import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; +//import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationFailureHandler; +//import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationSuccessHandler; +//import com.ttubeog.global.config.security.token.CustomAuthenticationEntryPoint; +//import com.ttubeog.global.config.security.token.CustomOncePerRequestFilter; +//import lombok.RequiredArgsConstructor; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.security.authentication.AuthenticationManager; +//import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +//import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +//import org.springframework.security.config.annotation.web.builders.HttpSecurity; +//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +//import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +//import org.springframework.security.config.http.SessionCreationPolicy; +//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +//import org.springframework.security.crypto.password.PasswordEncoder; +//import org.springframework.security.web.SecurityFilterChain; +//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +// +//import static org.springframework.security.config.Customizer.withDefaults; +// +// +//@RequiredArgsConstructor +//@Configuration +//@EnableWebSecurity +//public class SecurityConfig { +// +// private final CustomMemberDetailsService customMemberDetailsService; +// private final CustomDefaultOAuth2UserService customOAuth2UserService; +// private final CustomSimpleUrlAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; +// private final CustomSimpleUrlAuthenticationFailureHandler oAuth2AuthenticationFailureHandler; +// private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; +// +// @Bean +// public PasswordEncoder passwordEncoder() { +// return new BCryptPasswordEncoder(); +// } +// +// @Bean +// public CustomOncePerRequestFilter customOncePerRequestFilter() { +// return new CustomOncePerRequestFilter(); +// } +// +// @Bean +// public DaoAuthenticationProvider authenticationProvider() { +// DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); +// +// authenticationProvider.setUserDetailsService(customMemberDetailsService); +// authenticationProvider.setPasswordEncoder(passwordEncoder()); +// +// return authenticationProvider; +// } +// +// @Bean +// public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { +// return authenticationConfiguration.getAuthenticationManager(); +// } +// +// @Bean +// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { +// http +// .cors(withDefaults()) +// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) +// .csrf(AbstractHttpConfigurer::disable) +// .formLogin(AbstractHttpConfigurer::disable) +// .httpBasic(AbstractHttpConfigurer::disable) +// .exceptionHandling(exception -> exception.authenticationEntryPoint(new CustomAuthenticationEntryPoint())) +// .authorizeHttpRequests(authorize -> authorize +// .requestMatchers("/", "/error", "/favicon.ico", "/**/*.png", "/**/*.gif", "/**/*.svg", "/**/*.jpg", "/**/*.html", "/**/*.css", "/**/*.js") +// .permitAll() +// .requestMatchers("/swagger", "/swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**", "/v3/api-docs/**") +// .permitAll() +// .requestMatchers("/login/**","/auth/**", "/oauth2/**") +// .permitAll() +// .requestMatchers("/blog/**") +// .permitAll() +// .anyRequest() +// .authenticated()) +// .oauth2Login(oauth2 -> oauth2 +// .authorizationEndpoint(authorization -> authorization +// .baseUri("/oauth2/authorize") +// .authorizationRequestRepository(customAuthorizationRequestRepository)) +// .redirectionEndpoint(redirection -> redirection +// .baseUri("/oauth2/callback/**")) +// .userInfoEndpoint(userInfo -> userInfo +// .userService(customOAuth2UserService)) +// .successHandler(oAuth2AuthenticationSuccessHandler) +// .failureHandler(oAuth2AuthenticationFailureHandler)); +// +// http.addFilterBefore(customOncePerRequestFilter(), UsernamePasswordAuthenticationFilter.class); +// return http.build(); +// } +// +//} diff --git a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfo.java b/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfo.java index 519f343f..802bd9d1 100644 --- a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfo.java +++ b/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfo.java @@ -22,4 +22,6 @@ public Map getAttributes() { public abstract String getEmail(); public abstract String getImageUrl(); + + public abstract String getRefreshToken(); } diff --git a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java b/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java index 182ab801..d0190425 100644 --- a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java +++ b/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java @@ -1,29 +1,29 @@ -package com.ttubeog.global.config.security.auth; - -import com.ttubeog.domain.member.domain.Provider; -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.auth.company.Kakao; - -import java.util.Map; - -public class OAuth2UserInfoFactory { - public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { -// if(registrationId.equalsIgnoreCase(Provider.google.toString())) { -// return new Google(attributes); -// } else if (registrationId.equalsIgnoreCase(Provider.facebook.toString())) { -// return new Facebook(attributes); -// } else if (registrationId.equalsIgnoreCase(Provider.github.toString())) { -// return new Github(attributes); -// } else if (registrationId.equalsIgnoreCase(Provider.naver.toString())) { -// return new Naver(attributes); -// } else if ~~ - if (registrationId.equalsIgnoreCase(Provider.kakao.toString())) { - return new Kakao(attributes); - } else if (registrationId.equalsIgnoreCase(Provider.apple.toString())) { - DefaultAssert.isAuthentication("애플 로그인은 구현 예정입니다."); - } else { - DefaultAssert.isAuthentication("해당 oauth2 기능은 지원하지 않습니다."); - } - return null; - } -} +//package com.ttubeog.global.config.security.auth; +// +//import com.ttubeog.domain.member.domain.Provider; +//import com.ttubeog.global.DefaultAssert; +//import com.ttubeog.global.config.security.auth.company.Kakao; +// +//import java.util.Map; +// +//public class OAuth2UserInfoFactory { +// public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { +//// if(registrationId.equalsIgnoreCase(Provider.google.toString())) { +//// return new Google(attributes); +//// } else if (registrationId.equalsIgnoreCase(Provider.facebook.toString())) { +//// return new Facebook(attributes); +//// } else if (registrationId.equalsIgnoreCase(Provider.github.toString())) { +//// return new Github(attributes); +//// } else if (registrationId.equalsIgnoreCase(Provider.naver.toString())) { +//// return new Naver(attributes); +//// } else if ~~ +// if (registrationId.equalsIgnoreCase(Provider.kakao.toString())) { +// return new Kakao(attributes); +// } else if (registrationId.equalsIgnoreCase(Provider.apple.toString())) { +// DefaultAssert.isAuthentication("애플 로그인은 구현 예정입니다."); +// } else { +// DefaultAssert.isAuthentication("해당 oauth2 기능은 지원하지 않습니다."); +// } +// return null; +// } +//} diff --git a/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java b/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java index 21749067..ccf5f01b 100644 --- a/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java +++ b/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java @@ -1,54 +1,57 @@ -package com.ttubeog.global.config.security.auth.company; - -import com.ttubeog.domain.member.domain.Provider; -import com.ttubeog.global.config.security.auth.OAuth2UserInfo; - -import java.util.Map; - -public class Kakao extends OAuth2UserInfo { - - public Kakao(Map attributes) { - super(attributes); - } - - @Override - public String getId() { - return attributes.get("id").toString(); - } - - @Override - public String getName() { - Map properties = (Map) attributes.get("properties"); - - if (properties == null) { - return null; - } - - return (String) properties.get("nickname"); - } - - @Override - public String getEmail() { - Map properties = (Map) attributes.get("kakao_account"); - if (properties == null) { - return null; - } - return (String) properties.get("email"); - } - - @Override - public String getImageUrl() { - Map properties = (Map) attributes.get("properties"); - - if (properties == null) { - return null; - } - - return (String) properties.get("thumbnail_image"); - } - - @Override - public String getProvider(){ - return Provider.kakao.toString(); - } -} +//package com.ttubeog.global.config.security.auth.company; +// +//import com.ttubeog.domain.member.domain.Provider; +//import com.ttubeog.global.config.security.auth.OAuth2UserInfo; +// +//import java.util.Map; +// +//public class Kakao extends OAuth2UserInfo { +// +// public Kakao(Map attributes) { +// super(attributes); +// } +// +// @Override +// public String getId() { +// return attributes.get("id").toString(); +// } +// +// @Override +// public String getName() { +// Map properties = (Map) attributes.get("properties"); +// +// if (properties == null) { +// return null; +// } +// +// return (String) properties.get("nickname"); +// } +// +// @Override +// public String getEmail() { +// Map properties = (Map) attributes.get("kakao_account"); +// if (properties == null) { +// return null; +// } +// return (String) properties.get("email"); +// } +// +// @Override +// public String getImageUrl() { +// Map properties = (Map) attributes.get("properties"); +// +// if (properties == null) { +// return null; +// } +// +// return (String) properties.get("thumbnail_image"); +// } +// +// @Override +// public String getProvider(){ +// return Provider.kakao.toString(); +// } +// +// @Override +// public String getRefreshToken() { return} +//} diff --git a/src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java b/src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java similarity index 89% rename from src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java rename to src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java index ea1970da..5e48850c 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/CurrentMember.java +++ b/src/main/java/com/ttubeog/global/config/security/token/CurrentUser.java @@ -8,6 +8,6 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @AuthenticationPrincipal -public @interface CurrentMember { +public @interface CurrentUser { } diff --git a/src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java similarity index 80% rename from src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java rename to src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java index e222aef5..afc6d046 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/MemberPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java @@ -13,7 +13,7 @@ import java.util.Map; @Getter -public class MemberPrincipal implements OAuth2User, UserDetails{ +public class UserPrincipal implements OAuth2User, UserDetails{ private final Member member; @@ -23,7 +23,7 @@ public class MemberPrincipal implements OAuth2User, UserDetails{ private final Collection authorities; private Map attributes; - public MemberPrincipal(Member member, Long id, String email, String password, Collection authorities) { + public UserPrincipal(Member member, Long id, String email, String password, Collection authorities) { this.member = member; this.id = id; this.email = email; @@ -31,9 +31,9 @@ public MemberPrincipal(Member member, Long id, String email, String password, Co this.authorities = authorities; } - public static MemberPrincipal create(final Member member) { + public static UserPrincipal create(final Member member) { List authorities = Collections.singletonList(new SimpleGrantedAuthority(member.getRole().getValue())); - return new MemberPrincipal( + return new UserPrincipal( member, member.getId(), member.getEmail(), @@ -42,10 +42,10 @@ public static MemberPrincipal create(final Member member) { ); } - public static MemberPrincipal create(Member member, Map attributes) { - MemberPrincipal memberPrincipal = MemberPrincipal.create(member); - memberPrincipal.setAttributes(attributes); - return memberPrincipal; + public static UserPrincipal create(Member member, Map attributes) { + UserPrincipal userPrincipal = UserPrincipal.create(member); + userPrincipal.setAttributes(attributes); + return userPrincipal; } public void setAttributes(Map attributes) { From 69f93acd5317941c9c6ffac333ead2b2dac3da87 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 15:50:05 +0900 Subject: [PATCH 034/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e7dee891..eaf4d38c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -36,25 +36,31 @@ jobs: OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} - OCCUPY_SWAGGER_SECRET: ${{ secrets.OCCUPY_SWAGGER_SECRET }} - OCCUPY_SECRET_DIR: src/main/resources + + OCCUPY_SECRET_DIR: ./src/main/resources OCCUPY_DB_SECRET_DIR: $OCCUPY_SECRET_DIR/database OCCUPY_OAUTH_SECRET_DIR: $OCCUPY_SECRET_DIR/oauth2 - OCCUPY_SWAGGER_SECRET_DIR: $OCCUPY_SECRET_DIR/swagger + OCCUPY_SECRET_DIR_FILE_NAME: application.yml OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml - OCCUPY_swagger_SECRET_DIR_FILE_NAME: application-springdoc.yml - run: - echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && + run: | + touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + + echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + echo $OCCUPY_DB_SECRET | base64 --decode > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME && - echo $OCCUPY_OAUTH_SECRET | base64 --decode > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME && - echo $OCCUPY_SWAGGER_SECRET | base64 --decode > $OCCUPY_SWAGGER_SECRET_DIR/$OCCUPY_SWAGGER_SECRET_DIR_FILE_NAME + echo $OCCUPY_OAUTH_SECRET | base64 --decode > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + - name: Run chmod to make gradlew executable run: chmod +x ./gradlew + shell: bash - name: Build with Gradle - uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 - with: - arguments: build \ No newline at end of file + run: ./gradlew clean build -x test + shell: bash \ No newline at end of file From 6f84f578c9f52fd97fb1d73ad2be25e5dfda8786 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 15:55:10 +0900 Subject: [PATCH 035/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index eaf4d38c..91f58879 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -38,8 +38,8 @@ jobs: OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} OCCUPY_SECRET_DIR: ./src/main/resources - OCCUPY_DB_SECRET_DIR: $OCCUPY_SECRET_DIR/database - OCCUPY_OAUTH_SECRET_DIR: $OCCUPY_SECRET_DIR/oauth2 + OCCUPY_DB_SECRET_DIR: ./src/main/resources/database + OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 OCCUPY_SECRET_DIR_FILE_NAME: application.yml OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml @@ -53,9 +53,6 @@ jobs: echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - echo $OCCUPY_DB_SECRET | base64 --decode > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME && - echo $OCCUPY_OAUTH_SECRET | base64 --decode > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - - name: Run chmod to make gradlew executable run: chmod +x ./gradlew From c74c38515e2ca449febf8e722a897062733552f0 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 16:01:22 +0900 Subject: [PATCH 036/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 91f58879..bbb2f9cc 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -37,9 +37,9 @@ jobs: OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} - OCCUPY_SECRET_DIR: ./src/main/resources - OCCUPY_DB_SECRET_DIR: ./src/main/resources/database - OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 + OCCUPY_SECRET_DIR: src/main/resources + OCCUPY_DB_SECRET_DIR: src/main/resources/database + OCCUPY_OAUTH_SECRET_DIR: src/main/resources/oauth2 OCCUPY_SECRET_DIR_FILE_NAME: application.yml OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml From 07354bae64964c97a309e6c76a544f52179f3bc6 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 16:03:36 +0900 Subject: [PATCH 037/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9D=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit store 쪽은 주석처리 했고, 혜택 중복 방급 방지 예외처리 했습니다. --- build.gradle | 3 +- .../benefit/application/BenefitService.java | 53 +++++++++++++++++++ .../repository/MemberBenefitRepository.java | 7 +++ .../benefit/dto/response/SaveBenefitRes.java | 49 +++++++++++++++++ .../OverlappingBenefitException.java | 7 +++ .../presentation/BenefitController.java | 16 ++++++ 6 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java create mode 100644 src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java diff --git a/build.gradle b/build.gradle index f746ce27..05608c45 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" - runtimeOnly 'com.mysql:mysql-connector-j' +// runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 9f39565f..3993a509 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -2,12 +2,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; +import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.store.domain.Store; @@ -21,6 +24,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; @RequiredArgsConstructor @@ -31,6 +36,7 @@ public class BenefitService { private final MemberRepository memberRepository; private final BenefitRepository benefitRepository; private final StoreRepository storeRepository; + private final MemberBenefitRepository memberBenefitRepository; // 혜택 생성 @Transactional @@ -118,4 +124,51 @@ public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefi return ResponseEntity.ok(apiResponse); } + //게임 성공 후 혜택 저장 + @Transactional + public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + + Optional memberOptional = memberRepository.findById(userPrincipal.getId()); + DefaultAssert.isOptionalPresent(memberOptional); + Member member = memberOptional.get(); + + Optional benefitOptional = benefitRepository.findById(benefitId); + DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); + Benefit benefit = benefitOptional.get(); + + //유저에게 이미 있는 benefit인지 확인 + List memberBenefitList = memberBenefitRepository.findAllByBenefitAndCreatedDateIsAfter(benefit, LocalDateTime.now().minusMonths(1)); + //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 + if (memberBenefitList.size() > 0) { + throw new OverlappingBenefitException(); + } + + MemberBenefit memberBenefit = MemberBenefit.builder() + .member(member) + .benefit(benefit) + .is_used(false) + .has_expired(false) + .build(); + + memberBenefitRepository.save(memberBenefit); + + SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() + .id(memberBenefit.getId()) + .benefitId(benefit.getId()) +// .storeId(memberBenefit.getBenefit().getStore().getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .isUsed(memberBenefit.getIs_used()) + .hasExpried(memberBenefit.getHas_expired()) + .createdAt(memberBenefit.getCreatedDate()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(saveBenefitRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index fd7f904c..5d05ccfd 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -1,9 +1,16 @@ package com.ttubeog.domain.benefit.domain.repository; +import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; +import java.util.List; + @Repository public interface MemberBenefitRepository extends JpaRepository { + + List findAllByBenefitAndCreatedDateIsAfter(Benefit benefit, LocalDateTime createdDate); + } diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java new file mode 100644 index 00000000..cd4762fc --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -0,0 +1,49 @@ +package com.ttubeog.domain.benefit.dto.response; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class SaveBenefitRes { + + @Schema(description = "ID", example = "1") + private Long id; + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + +// @Schema(description = "매장 ID", example = "1") +// private Long storeId; + + @Schema(description = "내용", example = "아메리카노 20% 할인") + private String content; + + @Schema(description = "혜택타입", example = "sale") + private BenefitType type; + + @Schema(description = "사용 여부", example = "false") + private Boolean isUsed; + + @Schema(description = "만료 여부", example = "false") + private Boolean hasExpried; + + @Schema(description = "혜택 저장 시간", example = "2024-01-12 09:30:50") + private LocalDateTime createdAt; + + @Builder +// public SaveBenefitRes(Long id, Long benefitId, Long storeId, String content, BenefitType type, Boolean isUsed, Boolean hasExpried, LocalDateTime createdAt) { + public SaveBenefitRes(Long id, Long benefitId, String content, BenefitType type, Boolean isUsed, Boolean hasExpried, LocalDateTime createdAt) { + this.id = id; + this.benefitId = benefitId; +// this.storeId = storeId; + this.content = content; + this.type = type; + this.isUsed = isUsed; + this.hasExpried = hasExpried; + this.createdAt = createdAt; + } +} diff --git a/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java b/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java new file mode 100644 index 00000000..2704be94 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.benefit.exception; + +public class OverlappingBenefitException extends RuntimeException { + + public OverlappingBenefitException() { + super("이미 저장된 쿠폰입니다. 만료기간이 지난 후 다시 받을 수 있습니다."); } +} diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index aa619b75..19e15346 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -74,4 +75,19 @@ public ResponseEntity updateBenefit( ) throws JsonProcessingException { return benefitService.updateBenefit(userPrincipal, updateBenefitReq); } + + //게임 성공 후 혜택 저장 + @Operation(summary = "혜택 저장", description = "게임 성공 후 혜택을 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 저장 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 저장 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("/{benefitId}") + public ResponseEntity saveBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "benefitId") Long benefitId + ) throws JsonProcessingException { + return benefitService.saveBenefit(userPrincipal, benefitId); + } } From 9befef4bd9d5f72bbd041d9142fa1b8e8f65d881 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 16:03:59 +0900 Subject: [PATCH 038/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index bbb2f9cc..5d5999d2 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -37,14 +37,17 @@ jobs: OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} - OCCUPY_SECRET_DIR: src/main/resources - OCCUPY_DB_SECRET_DIR: src/main/resources/database - OCCUPY_OAUTH_SECRET_DIR: src/main/resources/oauth2 + OCCUPY_SECRET_DIR: ./src/main/resources + OCCUPY_DB_SECRET_DIR: ./src/main/resources/database + OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 OCCUPY_SECRET_DIR_FILE_NAME: application.yml OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml run: | + mkdir $OCCUPY_DB_SECRET_DIR + mkdir $OCCUPY_OAUTH_SECRET_DIR + touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME From 4cee49bb2b479f6a1576de42761aa1624f32fa6d Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 16:06:07 +0900 Subject: [PATCH 039/356] =?UTF-8?q?[Chore]=20BaseEntity=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreatedDate -> CreatedDate modifiedDate -> modifiedAt --- .../ttubeog/domain/benefit/application/BenefitService.java | 4 ++-- .../benefit/domain/repository/MemberBenefitRepository.java | 2 +- src/main/java/com/ttubeog/domain/common/BaseEntity.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 3993a509..11c9d5c5 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -137,7 +137,7 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId Benefit benefit = benefitOptional.get(); //유저에게 이미 있는 benefit인지 확인 - List memberBenefitList = memberBenefitRepository.findAllByBenefitAndCreatedDateIsAfter(benefit, LocalDateTime.now().minusMonths(1)); + List memberBenefitList = memberBenefitRepository.findAllByBenefitAndCreatedAtIsAfter(benefit, LocalDateTime.now().minusMonths(1)); //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 if (memberBenefitList.size() > 0) { throw new OverlappingBenefitException(); @@ -160,7 +160,7 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId .type(benefit.getType()) .isUsed(memberBenefit.getIs_used()) .hasExpried(memberBenefit.getHas_expired()) - .createdAt(memberBenefit.getCreatedDate()) + .createdAt(memberBenefit.getCreatedAt()) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 5d05ccfd..00ec788d 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -11,6 +11,6 @@ @Repository public interface MemberBenefitRepository extends JpaRepository { - List findAllByBenefitAndCreatedDateIsAfter(Benefit benefit, LocalDateTime createdDate); + List findAllByBenefitAndCreatedAtIsAfter(Benefit benefit, LocalDateTime createdAt); } diff --git a/src/main/java/com/ttubeog/domain/common/BaseEntity.java b/src/main/java/com/ttubeog/domain/common/BaseEntity.java index 8ee394cb..a9f082e8 100644 --- a/src/main/java/com/ttubeog/domain/common/BaseEntity.java +++ b/src/main/java/com/ttubeog/domain/common/BaseEntity.java @@ -17,9 +17,9 @@ public abstract class BaseEntity { @CreatedDate @Column(updatable=false) - private LocalDateTime createdDate; + private LocalDateTime createdAt; @LastModifiedDate - private LocalDateTime modifiedDate; + private LocalDateTime modifiedAt; } \ No newline at end of file From 742e8660cca6581c12b54b84ede759dfc5deeadb Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 16:12:58 +0900 Subject: [PATCH 040/356] =?UTF-8?q?[Chore]=20gradle.yml,=20.gitignore=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20gradle.yml=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20.gitignore=EC=97=90=20application.yml=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 --- .github/workflows/gradle.yml | 12 +++++++++--- .gitignore | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5d5999d2..6c7439ac 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -23,14 +23,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 + - name: Checkout branch + uses: actions/checkout@v3 + # java 버전 세팅 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' + # git ignore한 yml 파일들 github secret에서 복사해 오기 - name: Copy secret env: OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} @@ -56,11 +60,13 @@ jobs: echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - + # gradlew 실행 권한 부여 - name: Run chmod to make gradlew executable run: chmod +x ./gradlew shell: bash + # Build -> jar 파일 생성 - name: Build with Gradle run: ./gradlew clean build -x test - shell: bash \ No newline at end of file + shell: bash + diff --git a/.gitignore b/.gitignore index 5ab638fc..eb9fa13a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,8 +42,9 @@ out/ .LSOverride ### Project security ### -/src/main/resources/database/ -/src/main/resources/oauth2/ +**/resources/application.yml +**/resources/database/ +**/resources/oauth2/ Dockerfile docker-compose.yaml deploy_*.sh From 4b62dd3e3f5fedbd10ba76a0bb32956dae4ab94c Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:13:49 +0900 Subject: [PATCH 041/356] Delete src/main/resources/application.yml --- src/main/resources/application.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/main/resources/application.yml diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index c311394b..00000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,27 +0,0 @@ -# logging 설정 -logging: - level: - org: - hibernate: - type: - descriptor: - sql: debug - -# console 색상 -spring: - output: - ansi: - enabled: always - mvc: - pathmatch: - matching-strategy: ant_path_matcher - - -# 오류 처리 -server: - error: - include-exception: true - include-stacktrace: always - - #port 설정 - port: 8080 \ No newline at end of file From 976fd8aaf0c9adb74abfb4443979116f71d4ed16 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 17:00:51 +0900 Subject: [PATCH 042/356] =?UTF-8?q?[Chore]=20Null=20check=20=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit optional 방법 -> exception throw 방법 수정 --- .../benefit/application/BenefitService.java | 36 ++++++------------- .../NonExistentBenefitException.java | 7 ++++ .../OverlappingBenefitException.java | 2 +- 3 files changed, 18 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/exception/NonExistentBenefitException.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 11c9d5c5..01298ff8 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -10,9 +10,11 @@ import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; +import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.DefaultAssert; @@ -26,7 +28,6 @@ import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; @RequiredArgsConstructor @Service @@ -42,13 +43,9 @@ public class BenefitService { @Transactional public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); -// Optional storeOptional = storeRepository.findById(createBenefitReq.getStoreId()); -// Store store; -// DefaultAssert.isOptionalPresent(storeOptional); -// store = storeOptional.get(); +// Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); Benefit benefit = Benefit.builder() .content(createBenefitReq.getContent()) @@ -77,12 +74,8 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi @Transactional public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional benefitOptional = benefitRepository.findById(benefitId); - DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); - Benefit benefit = benefitOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); benefitRepository.delete(benefit); @@ -98,12 +91,8 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit @Transactional public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional benefitOptional = benefitRepository.findById(updateBenefitReq.getBenefitId()); - DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); - Benefit benefit = benefitOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); //TODO userOptional과 benefit의 userId가 일치하는지 확인 @@ -128,13 +117,8 @@ public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefi @Transactional public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - Member member = memberOptional.get(); - - Optional benefitOptional = benefitRepository.findById(benefitId); - DefaultAssert.isTrue(benefitOptional.isPresent(), "존재하지 않는 혜택입니다."); - Benefit benefit = benefitOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //유저에게 이미 있는 benefit인지 확인 List memberBenefitList = memberBenefitRepository.findAllByBenefitAndCreatedAtIsAfter(benefit, LocalDateTime.now().minusMonths(1)); diff --git a/src/main/java/com/ttubeog/domain/benefit/exception/NonExistentBenefitException.java b/src/main/java/com/ttubeog/domain/benefit/exception/NonExistentBenefitException.java new file mode 100644 index 00000000..817ad2d6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/exception/NonExistentBenefitException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.benefit.exception; + +public class NonExistentBenefitException extends RuntimeException{ + + public NonExistentBenefitException() { + super("존재하지 않는 혜택입니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java b/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java index 2704be94..14be9fa4 100644 --- a/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java +++ b/src/main/java/com/ttubeog/domain/benefit/exception/OverlappingBenefitException.java @@ -3,5 +3,5 @@ public class OverlappingBenefitException extends RuntimeException { public OverlappingBenefitException() { - super("이미 저장된 쿠폰입니다. 만료기간이 지난 후 다시 받을 수 있습니다."); } + super("이미 저장된 쿠폰입니다. 만료기간이 지난 후 다시 받을 수 있습니다.");} } From fecedade1f804eed1169f6b95e40eadff8d78831 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 17:02:14 +0900 Subject: [PATCH 043/356] [Chore] add appspec.yml --- appspec.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 appspec.yml diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 00000000..08ab1718 --- /dev/null +++ b/appspec.yml @@ -0,0 +1,27 @@ +# appspec.yml + +version: 0.0 +os: linux + +files: + - source: / + destination: /home/ubuntu/app # (ec2)인스턴스에서 파일이 저장될 위치 + overwrite: true +file_exists_behavior: OVERWRITE + +permissions: + - object: / + pattern: "**" + owner: ubuntu + group: ubuntu + mode: 775 + +hooks: + AfterInstall: + - location: scripts/stop.sh + timeout: 60 + runas: ubuntu + ApplicationStart: + - location: scripts/start.sh + timeout: 600 + runas: ubuntu \ No newline at end of file From 961ae8dab08226d17fc2615a26da54fc6f6be91c Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 17:06:25 +0900 Subject: [PATCH 044/356] [Chore] add scripts dir & modify build.gradle add scripts dir add deploy.sh add start.sh add stop.sh modify build.gradle --- build.gradle | 4 ++++ scripts/deploy.sh | 31 +++++++++++++++++++++++++++++++ scripts/start.sh | 21 +++++++++++++++++++++ scripts/stop.sh | 19 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 scripts/deploy.sh create mode 100644 scripts/start.sh create mode 100644 scripts/stop.sh diff --git a/build.gradle b/build.gradle index c241d2db..57b1329e 100644 --- a/build.gradle +++ b/build.gradle @@ -42,3 +42,7 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +jar { + enabled = false +} \ No newline at end of file diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 00000000..2df7ff8e --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +REPOSITORY=/home/ubuntu/app +cd $REPOSITORY + +# 1) 애플리케이션이 구동중인지 확인하기 위한 애플리케이션 이름, jar 파일의 이름 +APP_NAME=RecordOfMemory +JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.jar' | tail -n 1) # `이 아닌 ' 사용해야함... +JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME + +# 2) 현재 인스턴스에서 애플리케이션이 구동중인지 확인, 구동중이면 종료 +CURRENT_PID=$(pgrep -f $APP_NAME) + +if [ -z $CURRENT_PID ] +then + echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." +else + echo "> kill -15 $CURRENT_PID" + sudo kill -15 $CURRENT_PID + sleep 5 +fi + +# 3) app 디렉토리 권한 수정 +cd /home/ubuntu +sudo chmod 775 app +sudo chown ubuntu app + +# 4) jar 파일을 배포 +echo "> $JAR_PATH 배포" +# nohup java -jar $JAR_PATH & +nohup java -jar $JAR_PATH > /dev/null 2>&1 & diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100644 index 00000000..126c2a23 --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +PROJECT_ROOT="/home/ubuntu/app" +JAR_FILE="$PROJECT_ROOT/spring-webapp.jar" + +APP_LOG="$PROJECT_ROOT/application.log" +ERROR_LOG="$PROJECT_ROOT/error.log" +DEPLOY_LOG="$PROJECT_ROOT/deploy.log" + +TIME_NOW=$(date +%c) + +# build 파일 복사 +echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG +cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE + +# jar 파일 실행 +echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG +nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG & + +CURRENT_PID=$(pgrep -f $JAR_FILE) +echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG \ No newline at end of file diff --git a/scripts/stop.sh b/scripts/stop.sh new file mode 100644 index 00000000..755d3473 --- /dev/null +++ b/scripts/stop.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +PROJECT_ROOT="/home/ubuntu/app" +JAR_FILE="$PROJECT_ROOT/spring-webapp.jar" + +DEPLOY_LOG="$PROJECT_ROOT/deploy.log" + +TIME_NOW=$(date +%c) + +# 현재 구동 중인 애플리케이션 pid 확인 +CURRENT_PID=$(pgrep -f $JAR_FILE) + +# 프로세스가 켜져 있으면 종료 +if [ -z $CURRENT_PID ]; then + echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG +else + echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG + kill -15 $CURRENT_PID +fi \ No newline at end of file From d86ecae1c75b34a6d63bc453aca71928a0a5397e Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 17:20:46 +0900 Subject: [PATCH 045/356] =?UTF-8?q?[Chore]=20modify=20gradle.yml=20AWS=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0(CD)=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 6c7439ac..29b4998b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,14 +13,20 @@ on: pull_request: branches: [ "dev" ] +env: + AWS_REGION: ap-northeast-2 + S3_BUCKET_NAME: s3-ttubeog + CODE_DEPLOY_APPLICATION_NAME: ttubeog-codedeploy + CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: ttubeog-deploy-group + permissions: contents: read jobs: build: - - runs-on: ubuntu-latest + name: Build + runs-on: ubuntu-22.04 steps: # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 @@ -70,3 +76,28 @@ jobs: run: ./gradlew clean build -x test shell: bash + # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + # (7) 빌드 결과물을 S3 버킷에 업로드 + - name: Upload to AWS S3 + run: | + aws deploy push \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --ignore-hidden-files \ + --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ + --source . + + # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 + - name: Deploy to AWS EC2 from S3 + run: | + aws deploy create-deployment \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --deployment-config-name CodeDeployDefault.AllAtOnce \ + --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip \ No newline at end of file From ec5ea1021921a401eb059065ce5fa621ca7dc4f9 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 18:08:32 +0900 Subject: [PATCH 046/356] =?UTF-8?q?[Chore]=20modify=20gradle.yml=20CD=20?= =?UTF-8?q?=ED=8C=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 49 ++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 29b4998b..289958c6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -76,7 +76,13 @@ jobs: run: ./gradlew clean build -x test shell: bash - # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + + deploy: + name: CD with SSH + needs: build + runs-on: ubuntu-22.04 + steps: + # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: @@ -94,10 +100,37 @@ jobs: --source . # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 - - name: Deploy to AWS EC2 from S3 - run: | - aws deploy create-deployment \ - --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - --deployment-config-name CodeDeployDefault.AllAtOnce \ - --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ - --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip \ No newline at end of file +# - name: Deploy to AWS EC2 from S3 +# run: | +# aws deploy create-deployment \ +# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ +# --deployment-config-name CodeDeployDefault.AllAtOnce \ +# --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ +# --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip + - name: Download build artifacts + uses: actions/download-artifact@v2 + with: + name: build-artifacts + + # JAR 파일을 EC2에 배포하는 step + - name: SCP JAR to EC2 + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + source: "*.jar" + target: "/home/ubuntu/app" + + # EC2에 SSH로 배포 커맨드를 입력하는 step + - name: Deploy SSH + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo fuser -k -n tcp 8080 + sleep 15 + sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file From 05c7bf4947733ac96c8208a65c6bf2c7ef31fecb Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 18:16:27 +0900 Subject: [PATCH 047/356] [Chore] modify gradle.yml --- .github/workflows/gradle.yml | 37 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 289958c6..4352f995 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -81,25 +81,26 @@ jobs: name: CD with SSH needs: build runs-on: ubuntu-22.04 - steps: - # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ env.AWS_REGION }} - - # (7) 빌드 결과물을 S3 버킷에 업로드 - - name: Upload to AWS S3 - run: | - aws deploy push \ - --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - --ignore-hidden-files \ - --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ - --source . - # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 + steps: +# # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) +# - name: Configure AWS credentials +# uses: aws-actions/configure-aws-credentials@v1 +# with: +# aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} +# aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} +# aws-region: ${{ env.AWS_REGION }} +# +# # (7) 빌드 결과물을 S3 버킷에 업로드 +# - name: Upload to AWS S3 +# run: | +# aws deploy push \ +# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ +# --ignore-hidden-files \ +# --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ +# --source . +# +# # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 # - name: Deploy to AWS EC2 from S3 # run: | # aws deploy create-deployment \ From 4d84117e1aaf83d275f21a9244fe1a9b26c75472 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 19 Jan 2024 18:19:59 +0900 Subject: [PATCH 048/356] [Chore] modify gradle.yml add upload artifact step to build job --- .github/workflows/gradle.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 4352f995..f8b3a88b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -38,7 +38,7 @@ jobs: uses: actions/setup-java@v3 with: java-version: '17' - distribution: 'temurin' + distribution: 'zulu' # git ignore한 yml 파일들 github secret에서 복사해 오기 - name: Copy secret @@ -76,6 +76,13 @@ jobs: run: ./gradlew clean build -x test shell: bash + - name: Upload Build artifacts + uses: actions/upload-artifact@v2 + with: + name: build-artifacts + path: | + build/libs/*.jar + deploy: name: CD with SSH From 6c4c6ba50168db9a015364fb27debdfa227e7a78 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 19 Jan 2024 18:29:26 +0900 Subject: [PATCH 049/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9D=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 멤버가 보유하고 있는 혜택을 사용하는 api입니다. 해당 혜택을 이미 사용한 경우, 해당하는 혜택이 없는 경우 예외 처리했습니다. --- .../benefit/application/BenefitService.java | 49 +++++++++++++++++-- .../domain/benefit/domain/MemberBenefit.java | 14 ++++-- .../repository/MemberBenefitRepository.java | 4 ++ .../benefit/dto/response/SaveBenefitRes.java | 14 +++--- .../AlreadyUsedBenefitException.java | 8 +++ .../InvalidMemberBenefitException.java | 9 ++++ .../presentation/BenefitController.java | 15 ++++++ 7 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/benefit/exception/AlreadyUsedBenefitException.java create mode 100644 src/main/java/com/ttubeog/domain/benefit/exception/InvalidMemberBenefitException.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 01298ff8..88bc22e5 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -10,6 +10,8 @@ import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; +import com.ttubeog.domain.benefit.exception.AlreadyUsedBenefitException; +import com.ttubeog.domain.benefit.exception.InvalidMemberBenefitException; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; import com.ttubeog.domain.member.domain.Member; @@ -130,8 +132,8 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId MemberBenefit memberBenefit = MemberBenefit.builder() .member(member) .benefit(benefit) - .is_used(false) - .has_expired(false) + .used(false) + .expired(false) .build(); memberBenefitRepository.save(memberBenefit); @@ -142,8 +144,8 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId // .storeId(memberBenefit.getBenefit().getStore().getId()) .content(benefit.getContent()) .type(benefit.getType()) - .isUsed(memberBenefit.getIs_used()) - .hasExpried(memberBenefit.getHas_expired()) + .used(memberBenefit.getUsed()) + .expried(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) .build(); @@ -155,4 +157,43 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId return ResponseEntity.ok(apiResponse); } + + //혜택 사용 + @Transactional + public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); + + //만료기간 안에 혜택은 오직 한개 + MemberBenefit memberBenefit = memberBenefitRepository.findByBenefitAndMemberAndExpiredIsFalse(benefit, member) + .orElseThrow(InvalidMemberBenefitException::new); + + //이미 사용한 혜택인지 확인 + if (memberBenefit.getUsed()) { + throw new AlreadyUsedBenefitException(); + } + + memberBenefit.useBenefit(); + + SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() + .id(memberBenefit.getId()) + .benefitId(benefit.getId()) +// .store(memberBenefit.store.getId()) + .used(memberBenefit.getUsed()) + .expried(memberBenefit.getExpired()) + .createdAt(memberBenefit.getCreatedAt()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(saveBenefitRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + //TODO 한달지나면 has_expired true로 만들기 } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java index 569b1b64..15689099 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java @@ -25,16 +25,20 @@ public class MemberBenefit extends BaseEntity { @JoinColumn(name = "benefit_id") private Benefit benefit; - private Boolean is_used = false; // 사용 여부 + private Boolean used = false; // 사용 여부 - private Boolean has_expired = false; // 만료 여부 + private Boolean expired = false; // 만료 여부 @Builder - public MemberBenefit(Long id, Member member, Benefit benefit, Boolean is_used, Boolean has_expired) { + public MemberBenefit(Long id, Member member, Benefit benefit, Boolean used, Boolean expired) { this.id = id; this.member = member; this.benefit = benefit; - this.is_used = is_used; - this.has_expired = has_expired; + this.used = used; + this.expired = expired; + } + + public void useBenefit() { + this.used = true; } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 00ec788d..1e9bdc94 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -2,15 +2,19 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; +import com.ttubeog.domain.member.domain.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; @Repository public interface MemberBenefitRepository extends JpaRepository { List findAllByBenefitAndCreatedAtIsAfter(Benefit benefit, LocalDateTime createdAt); + Optional findByBenefitAndMemberAndExpiredIsFalse(Benefit benefit, Member member); + } diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java index cd4762fc..24edb287 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -10,7 +10,7 @@ @Data public class SaveBenefitRes { - @Schema(description = "ID", example = "1") + @Schema(description = "멤버-혜택ID", example = "1") private Long id; @Schema(description = "혜택 ID", example = "1") @@ -26,24 +26,24 @@ public class SaveBenefitRes { private BenefitType type; @Schema(description = "사용 여부", example = "false") - private Boolean isUsed; + private Boolean used; @Schema(description = "만료 여부", example = "false") - private Boolean hasExpried; + private Boolean expried; @Schema(description = "혜택 저장 시간", example = "2024-01-12 09:30:50") private LocalDateTime createdAt; @Builder -// public SaveBenefitRes(Long id, Long benefitId, Long storeId, String content, BenefitType type, Boolean isUsed, Boolean hasExpried, LocalDateTime createdAt) { - public SaveBenefitRes(Long id, Long benefitId, String content, BenefitType type, Boolean isUsed, Boolean hasExpried, LocalDateTime createdAt) { +// public SaveBenefitRes(Long id, Long benefitId, Long storeId, String content, BenefitType type, Boolean isUsed, Boolean expried, LocalDateTime createdAt) { + public SaveBenefitRes(Long id, Long benefitId, String content, BenefitType type, Boolean used, Boolean expried, LocalDateTime createdAt) { this.id = id; this.benefitId = benefitId; // this.storeId = storeId; this.content = content; this.type = type; - this.isUsed = isUsed; - this.hasExpried = hasExpried; + this.used = used; + this.expried = expried; this.createdAt = createdAt; } } diff --git a/src/main/java/com/ttubeog/domain/benefit/exception/AlreadyUsedBenefitException.java b/src/main/java/com/ttubeog/domain/benefit/exception/AlreadyUsedBenefitException.java new file mode 100644 index 00000000..1fd2bb29 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/exception/AlreadyUsedBenefitException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.benefit.exception; + +public class AlreadyUsedBenefitException extends RuntimeException { + + public AlreadyUsedBenefitException(){ + super("이미 사용된 혜택입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/benefit/exception/InvalidMemberBenefitException.java b/src/main/java/com/ttubeog/domain/benefit/exception/InvalidMemberBenefitException.java new file mode 100644 index 00000000..c94e8f3d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/benefit/exception/InvalidMemberBenefitException.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.benefit.exception; + +public class InvalidMemberBenefitException extends RuntimeException { + + public InvalidMemberBenefitException(){ + super("유저에 저장된 혜택이 올바르지 않습니다."); + } + +} diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 19e15346..5452525d 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -90,4 +90,19 @@ public ResponseEntity saveBenefit( ) throws JsonProcessingException { return benefitService.saveBenefit(userPrincipal, benefitId); } + + //혜택 사용 + @Operation(summary = "혜택 사용", description = "멤버가 보유 중인 혜택을 사용합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 사용 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 사용 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("{benefitId}/use") + public ResponseEntity useBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "benefitId") Long benefitId + ) throws JsonProcessingException { + return benefitService.useBenefit(userPrincipal, benefitId); + } } From 2c260eb97f9f9531201aa5230101dbcb35d17159 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:09:23 +0900 Subject: [PATCH 050/356] =?UTF-8?q?[Chore]=20Discord=20log=20back=20Discor?= =?UTF-8?q?d=EC=99=80=20=EC=97=B0=EB=8F=99=ED=95=B4=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=EA=B0=80=20=EB=B0=9C=EC=83=9D=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20=EB=B0=94=EB=A1=9C=20discord=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + build.gradle | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index eb9fa13a..9b4ecbd6 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ out/ **/resources/application.yml **/resources/database/ **/resources/oauth2/ +**/resources/logback.xml Dockerfile docker-compose.yaml deploy_*.sh diff --git a/build.gradle b/build.gradle index 57b1329e..0c98f1f5 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,9 @@ sourceCompatibility = '17' repositories { mavenCentral() + + // discord log back + maven { url 'https://jitpack.io' } } dependencies { @@ -33,10 +36,12 @@ dependencies { annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" runtimeOnly 'com.mysql:mysql-connector-j' - implementation 'org.mariadb.jdbc:mariadb-java-client:2.6.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' + + // discord log back + implementation 'com.github.napstr:logback-discord-appender:1.0.0' } tasks.named('test') { From 9ccdf81a6440fd0074511518076e5a25b658cdaa Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 20 Jan 2024 18:28:15 +0900 Subject: [PATCH 051/356] =?UTF-8?q?[Feat]=20MemberMapper=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- ...ityDomainConfig.java => SecurityConfig.java} | 14 +++++++++++--- .../ttubeog/domain/auth/filter/JwtFilter.java | 5 +++++ .../member/application/MemberService.java | 17 +++++++++-------- .../domain/member/mapper/MemberMapper.java | 13 +++++++++++++ 5 files changed, 39 insertions(+), 12 deletions(-) rename src/main/java/com/ttubeog/domain/auth/config/{SecurityDomainConfig.java => SecurityConfig.java} (84%) create mode 100644 src/main/java/com/ttubeog/domain/member/mapper/MemberMapper.java diff --git a/build.gradle b/build.gradle index 57b1329e..d7c64334 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-webflux' - + implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.2' implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0' testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.3.0' diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java similarity index 84% rename from src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java rename to src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index e4b60c46..6c0b94b8 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityDomainConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -9,6 +9,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @@ -17,11 +18,11 @@ @RequiredArgsConstructor @Configuration -public class SecurityDomainConfig { +public class SecurityConfig { private final JwtTokenService jwtTokenService; private final MemberService memberService; - @Bean(name = "domainAuth") + @Bean public AuthenticationManager authenticationManager( final AuthenticationConfiguration authenticationConfiguration ) throws Exception { @@ -33,7 +34,7 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc return httpSecurity.cors(withDefaults()) .csrf((csrf) -> csrf.disable()) .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/auth/login/**", "/token/refresh").permitAll() + .requestMatchers("/auth/login/**").permitAll() .anyRequest().authenticated()) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 @@ -41,4 +42,11 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .addFilterBefore(new JwtFilter(jwtTokenService, memberService), UsernamePasswordAuthenticationFilter.class) // JWT 필터 추가 .build(); } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer(){ + return web -> + web.ignoring() + .requestMatchers("/auth/login/**"); + } } diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 2b5fcaed..504f950b 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.auth.application.JwtTokenService; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.dto.MemberDto; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; @@ -25,6 +26,10 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); String jwt = resolveToken(httpServletRequest); + + if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { + Long memberId = Long.valueOf(jwtTokenService.getPayload(jwt)); + } } // 헤더에서 액세스 토큰 가져오는 코드 diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index baf6cee7..3b37058d 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.mapper.MemberMapper; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; @@ -19,6 +20,7 @@ @Transactional(readOnly = true) public class MemberService { private final MemberRepository memberRepository; + private final MemberMapper memberMapper; // 현재 유저 조회 public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ @@ -42,9 +44,7 @@ public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ } public MemberDto findById(Long id) { - Optional member = memberRepository.findById(id); - - return member.map(MemberDto::toEntity).orElse(null); + return memberMapper.findById(id); } public MemberDto findByRefreshToken(String refreshToken) { @@ -52,15 +52,16 @@ public MemberDto findByRefreshToken(String refreshToken) { return member.map(MemberDto::toEntity).orElse(null); } - public void save(MemberDto memberDetailRes) { - + public void save(MemberDto memberDto) { + memberMapper.save(memberDto); } - public void update(MemberDto memberDetailRes) { - + public void update(MemberDto memberDto) { + memberMapper.update(memberDto); } - public void updateRefreshToken(MemberDto memberDetailRes) { + public void updateRefreshToken(MemberDto memberDto) { + memberMapper.updateRefreshToken(memberDto); } } diff --git a/src/main/java/com/ttubeog/domain/member/mapper/MemberMapper.java b/src/main/java/com/ttubeog/domain/member/mapper/MemberMapper.java new file mode 100644 index 00000000..1715b397 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/mapper/MemberMapper.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.member.mapper; + +import com.ttubeog.domain.member.dto.MemberDto; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MemberMapper { + void save(MemberDto memberDto); + MemberDto findById(Long id); + MemberDto findByRefreshToken(String refreshToken); + void update(MemberDto memberDto); + void updateRefreshToken(MemberDto memberDto); +} From 21579b3f55bf4b348f2cb8b20d6f4c9ef5224cef Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 20 Jan 2024 18:56:11 +0900 Subject: [PATCH 052/356] =?UTF-8?q?[Feat]=20JWT=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomMemberDetailsService.java | 82 ++++++++--------- .../CustomTokenProviderService.java | 28 +++--- .../ttubeog/domain/auth/filter/JwtFilter.java | 18 ++++ .../ttubeog/domain/member/domain/Member.java | 6 +- .../domain/{Role.java => MemberRole.java} | 12 ++- .../ttubeog/domain/member/dto/MemberDto.java | 1 + .../token/CustomOncePerRequestFilter.java | 92 +++++++++---------- .../config/security/token/UserPrincipal.java | 30 +++--- 8 files changed, 148 insertions(+), 121 deletions(-) rename src/main/java/com/ttubeog/domain/member/domain/{Role.java => MemberRole.java} (53%) diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java index cb94a0c1..a3a1ba82 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java @@ -1,41 +1,41 @@ -package com.ttubeog.domain.auth.application; - -import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.domain.repository.MemberRepository; -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@RequiredArgsConstructor -@Service -public class CustomMemberDetailsService implements UserDetailsService{ - - private final MemberRepository memberRepository; - - @Override - public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { - - Member member = memberRepository.findByEmail(email) - .orElseThrow(() -> - new UsernameNotFoundException("멤버 정보를 찾을 수 없습니다.") - ); - - return UserPrincipal.create(member); - } - - @Transactional - public UserDetails loadUserById(Long id) { - Optional user = memberRepository.findById(id); - DefaultAssert.isOptionalPresent(user); - - return UserPrincipal.create(user.get()); - } - -} +//package com.ttubeog.domain.auth.application; +// +//import com.ttubeog.domain.member.domain.Member; +//import com.ttubeog.domain.member.domain.repository.MemberRepository; +//import com.ttubeog.global.DefaultAssert; +//import com.ttubeog.global.config.security.token.UserPrincipal; +//import jakarta.transaction.Transactional; +//import lombok.RequiredArgsConstructor; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.core.userdetails.UserDetailsService; +//import org.springframework.security.core.userdetails.UsernameNotFoundException; +//import org.springframework.stereotype.Service; +// +//import java.util.Optional; +// +//@RequiredArgsConstructor +//@Service +//public class CustomMemberDetailsService implements UserDetailsService{ +// +// private final MemberRepository memberRepository; +// +// @Override +// public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { +// +// Member member = memberRepository.findByEmail(email) +// .orElseThrow(() -> +// new UsernameNotFoundException("멤버 정보를 찾을 수 없습니다.") +// ); +// +// return UserPrincipal.create(member); +// } +// +// @Transactional +// public UserDetails loadUserById(Long id) { +// Optional user = memberRepository.findById(id); +// DefaultAssert.isOptionalPresent(user); +// +// return UserPrincipal.create(user.get()); +// } +// +//} diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java index 2b56e6c3..2cdd9324 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java +++ b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java @@ -23,8 +23,8 @@ public class CustomTokenProviderService { @Autowired private OAuth2Config oAuth2Config; - @Autowired - private CustomMemberDetailsService customMemberDetailsService; +// @Autowired +// private CustomMemberDetailsService customMemberDetailsService; public TokenMapping refreshToken(Authentication authentication, String refreshToken) { UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); @@ -92,18 +92,18 @@ public Long getUserIdFromToken(String token) { return Long.parseLong(claims.getSubject()); } - public UsernamePasswordAuthenticationToken getAuthenticationById(String token){ - Long userId = getUserIdFromToken(token); - UserDetails userDetails = customMemberDetailsService.loadUserById(userId); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - return authentication; - } - - public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String email){ - UserDetails userDetails = customMemberDetailsService.loadUserByUsername(email); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - return authentication; - } +// public UsernamePasswordAuthenticationToken getAuthenticationById(String token){ +// Long userId = getUserIdFromToken(token); +// UserDetails userDetails = customMemberDetailsService.loadUserById(userId); +// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); +// return authentication; +// } +// +// public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String email){ +// UserDetails userDetails = customMemberDetailsService.loadUserByUsername(email); +// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); +// return authentication; +// } public Long getExpiration(String token) { // accessToken 남은 유효시간 diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 504f950b..4504efee 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -3,12 +3,19 @@ import com.ttubeog.domain.auth.application.JwtTokenService; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.StringUtils; import org.springframework.web.filter.GenericFilterBean; @@ -29,7 +36,18 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { Long memberId = Long.valueOf(jwtTokenService.getPayload(jwt)); + MemberDto member = memberService.findById(memberId); + if (member == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + UserDetails memberDetails = UserPrincipal.create(member); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(memberDetails, null, memberDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } else { + throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); } + + filterChain.doFilter(servletRequest, servletResponse); } // 헤더에서 액세스 토큰 가져오는 코드 diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 5f0cde49..0f89f026 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -30,7 +30,7 @@ public class Member extends BaseEntity { private Provider provider; @Enumerated(EnumType.STRING) - private Role role; + private MemberRole memberRole; private String providerId; @@ -38,14 +38,14 @@ public class Member extends BaseEntity { private String refreshToken; @Builder - public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, Role role, String providerId, String platform, String refreshToken) { + public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String providerId, String platform, String refreshToken) { this.id = id; this.name = name; this.email = email; this.imageUrl = imageUrl; this.password = password; this.provider = provider; - this.role = role; + this.memberRole = memberRole; this.providerId = providerId; this.platform = platform; this.refreshToken = refreshToken; diff --git a/src/main/java/com/ttubeog/domain/member/domain/Role.java b/src/main/java/com/ttubeog/domain/member/domain/MemberRole.java similarity index 53% rename from src/main/java/com/ttubeog/domain/member/domain/Role.java rename to src/main/java/com/ttubeog/domain/member/domain/MemberRole.java index 74af748f..74b0abfe 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Role.java +++ b/src/main/java/com/ttubeog/domain/member/domain/MemberRole.java @@ -3,11 +3,17 @@ import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor -@Getter -public enum Role { +public enum MemberRole { ADMIN("ROLE_ADMIN"), USER("ROLE_USER"); private String value; + + MemberRole(String value) { + this.value = value; + } + + public String getRole() { + return value; + } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java index 9eefaa7d..4f160f8f 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -14,6 +14,7 @@ public class MemberDto { private Long id; private String email; private String name; + private String password; private String platform; private String refreshToken; diff --git a/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java b/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java index b414136e..dea31ffe 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java +++ b/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java @@ -1,46 +1,46 @@ -package com.ttubeog.global.config.security.token; - -import com.ttubeog.domain.auth.application.CustomTokenProviderService; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -@Slf4j -public class CustomOncePerRequestFilter extends OncePerRequestFilter{ - - @Autowired - private CustomTokenProviderService customTokenProviderService; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String jwt = getJwtFromRequest(request); - - if (StringUtils.hasText(jwt) && customTokenProviderService.validateToken(jwt)) { - UsernamePasswordAuthenticationToken authentication = customTokenProviderService.getAuthenticationById(jwt); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - - filterChain.doFilter(request, response); - } - - private String getJwtFromRequest(HttpServletRequest request) { - String bearerToken = request.getHeader("Authorization"); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer")) { - log.info("bearerToken = {}", bearerToken.substring(7, bearerToken.length())); - return bearerToken.substring(7, bearerToken.length()); - } - return null; - } - -} +//package com.ttubeog.global.config.security.token; +// +//import com.ttubeog.domain.auth.application.CustomTokenProviderService; +//import jakarta.servlet.FilterChain; +//import jakarta.servlet.ServletException; +//import jakarta.servlet.http.HttpServletRequest; +//import jakarta.servlet.http.HttpServletResponse; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +//import org.springframework.util.StringUtils; +//import org.springframework.web.filter.OncePerRequestFilter; +// +//import java.io.IOException; +// +//@Slf4j +//public class CustomOncePerRequestFilter extends OncePerRequestFilter{ +// +//// @Autowired +//// private CustomTokenProviderService customTokenProviderService; +// +// @Override +// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { +// String jwt = getJwtFromRequest(request); +// +//// if (StringUtils.hasText(jwt) && customTokenProviderService.validateToken(jwt)) { +//// UsernamePasswordAuthenticationToken authentication = customTokenProviderService.getAuthenticationById(jwt); +//// authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); +//// SecurityContextHolder.getContext().setAuthentication(authentication); +//// } +// +// filterChain.doFilter(request, response); +// } +// +// private String getJwtFromRequest(HttpServletRequest request) { +// String bearerToken = request.getHeader("Authorization"); +// if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer")) { +// log.info("bearerToken = {}", bearerToken.substring(7, bearerToken.length())); +// return bearerToken.substring(7, bearerToken.length()); +// } +// return null; +// } +// +//} diff --git a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java index afc6d046..107d4720 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java @@ -1,6 +1,7 @@ package com.ttubeog.global.config.security.token; -import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.MemberRole; +import com.ttubeog.domain.member.dto.MemberDto; import lombok.Getter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -15,15 +16,16 @@ @Getter public class UserPrincipal implements OAuth2User, UserDetails{ - private final Member member; + private final MemberDto member; private final Long id; private final String email; private final String password; private final Collection authorities; + @Getter private Map attributes; - public UserPrincipal(Member member, Long id, String email, String password, Collection authorities) { + public UserPrincipal(MemberDto member, Long id, String email, String password, Collection authorities) { this.member = member; this.id = id; this.email = email; @@ -31,8 +33,8 @@ public UserPrincipal(Member member, Long id, String email, String password, Coll this.authorities = authorities; } - public static UserPrincipal create(final Member member) { - List authorities = Collections.singletonList(new SimpleGrantedAuthority(member.getRole().getValue())); + public static UserPrincipal create(MemberDto member) { + List authorities = Collections.singletonList(new SimpleGrantedAuthority(MemberRole.USER.getRole())); return new UserPrincipal( member, member.getId(), @@ -42,11 +44,6 @@ public static UserPrincipal create(final Member member) { ); } - public static UserPrincipal create(Member member, Map attributes) { - UserPrincipal userPrincipal = UserPrincipal.create(member); - userPrincipal.setAttributes(attributes); - return userPrincipal; - } public void setAttributes(Map attributes) { this.attributes = attributes; @@ -60,6 +57,11 @@ public String getEmail() { return email; } + @Override + public A getAttribute(String name) { + return OAuth2User.super.getAttribute(name); + } + @Override public Map getAttributes() { return attributes; @@ -71,13 +73,13 @@ public Collection getAuthorities() { } @Override - public String getName() { - return String.valueOf(id); + public String getPassword() { + return null; } @Override - public String getPassword() { - return password; + public String getName() { + return String.valueOf(id); } @Override From 6fc8537a196bccecf6fcaf0c04a810cf4ebf1257 Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 20 Jan 2024 19:06:18 +0900 Subject: [PATCH 053/356] =?UTF-8?q?[Feat]=20SecurityUtil=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 2 +- .../auth/controller/OauthController.java | 3 +- .../ttubeog/domain/auth/filter/JwtFilter.java | 3 +- .../JwtTokenService.java | 8 ++++-- .../KakaoOauthService.java | 2 +- .../OauthService.java | 8 +++++- .../domain/auth/utils/SecurityUtil.java | 28 +++++++++++++++++++ 7 files changed, 45 insertions(+), 9 deletions(-) rename src/main/java/com/ttubeog/domain/auth/{application => service}/JwtTokenService.java (93%) rename src/main/java/com/ttubeog/domain/auth/{application => service}/KakaoOauthService.java (97%) rename src/main/java/com/ttubeog/domain/auth/{application => service}/OauthService.java (81%) create mode 100644 src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 6c0b94b8..28ae461a 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,6 +1,6 @@ package com.ttubeog.domain.auth.config; -import com.ttubeog.domain.auth.application.JwtTokenService; +import com.ttubeog.domain.auth.service.JwtTokenService; import com.ttubeog.domain.auth.filter.JwtFilter; import com.ttubeog.domain.member.application.MemberService; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 0e505a56..0f447af7 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -1,11 +1,10 @@ package com.ttubeog.domain.auth.controller; -import com.ttubeog.domain.auth.application.OauthService; +import com.ttubeog.domain.auth.service.OauthService; import com.ttubeog.domain.auth.dto.OauthRequestDto; import com.ttubeog.domain.auth.dto.OauthResponseDto; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 4504efee..ba591801 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -1,9 +1,8 @@ package com.ttubeog.domain.auth.filter; -import com.ttubeog.domain.auth.application.JwtTokenService; +import com.ttubeog.domain.auth.service.JwtTokenService; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.error.DefaultException; import com.ttubeog.global.payload.ErrorCode; diff --git a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java similarity index 93% rename from src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java rename to src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java index c9246c54..944d569f 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -1,5 +1,7 @@ -package com.ttubeog.domain.auth.application; +package com.ttubeog.domain.auth.service; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; @@ -35,7 +37,7 @@ public JwtTokenService( } @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { key = getKeyFromBase64EncodedKey(encodeBase64SecretKey(secretKey)); } @@ -80,6 +82,8 @@ public String getPayload(String token) { .getSubject(); } catch (ExpiredJwtException e) { return e.getClaims().getSubject(); + } catch (JwtException e) { + throw new DefaultException(ErrorCode.INVALID_AUTHENTICATION); } } diff --git a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java similarity index 97% rename from src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java rename to src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java index 864c7e0b..81f0ce14 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.application; +package com.ttubeog.domain.auth.service; import com.ttubeog.domain.auth.dto.KakaoInfoDto; diff --git a/src/main/java/com/ttubeog/domain/auth/application/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java similarity index 81% rename from src/main/java/com/ttubeog/domain/auth/application/OauthService.java rename to src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 1f436923..188068f5 100644 --- a/src/main/java/com/ttubeog/domain/auth/application/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -1,7 +1,9 @@ -package com.ttubeog.domain.auth.application; +package com.ttubeog.domain.auth.service; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -36,7 +38,11 @@ public String refreshToAccessToken(String refreshToken) { MemberDto memberDto = memberService.findByRefreshToken(refreshToken); if(memberDto == null) { + throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); + } + if (!jwtTokenService.validateToken(refreshToken)) { + throw new DefaultException(ErrorCode.INVALID_CHECK); } return jwtTokenService.createAccessToken(memberDto.getId().toString()); diff --git a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java new file mode 100644 index 00000000..e37859ed --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java @@ -0,0 +1,28 @@ +package com.ttubeog.domain.auth.utils; + +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +public class SecurityUtil { + private SecurityUtil() {} + + public static long getCurrentMemeberId() { + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + long memberId; + + if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { + memberId = userPrincipal.getId(); + } else { + throw new DefaultException(ErrorCode.INVALID_PARAMETER); + } + return memberId; + } +} From 7926d538a420e16d635141ea38390d3580bdfceb Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 20 Jan 2024 19:15:06 +0900 Subject: [PATCH 054/356] =?UTF-8?q?[Feat]=20Oauth=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/OauthController.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 0f447af7..198d77a9 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -1,29 +1,61 @@ package com.ttubeog.domain.auth.controller; -import com.ttubeog.domain.auth.service.OauthService; import com.ttubeog.domain.auth.dto.OauthRequestDto; import com.ttubeog.domain.auth.dto.OauthResponseDto; +import com.ttubeog.domain.auth.dto.RefreshTokenResponseDto; +import com.ttubeog.domain.auth.service.OauthService; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; +import java.util.stream.Collectors; + @RestController @RequiredArgsConstructor +@RequestMapping("/auth") public class OauthController { private final OauthService oauthService; // 카카오 로그인 - @PostMapping("/auth/login/kakao") + @PostMapping("/login/kakao") public OauthResponseDto loginWithKaKao( @RequestBody OauthRequestDto oauthRequestDto, HttpServletResponse response ) { OauthResponseDto oauthResponseDto = new OauthResponseDto(); - String accessToken = oauthService.loginWithKakao(oauthResponseDto.getAccessToken(), response); + String accessToken = oauthService.loginWithKakao(oauthRequestDto.getAccessToken(), response); oauthResponseDto.setAccessToken(accessToken); return oauthResponseDto; } + + // 리프레시 토큰으로 액세스토큰 재발급 + @PostMapping("/token/refresh") + public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { + RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); + Cookie[] list = request.getCookies(); + + if (list == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> + cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); + + if (refreshTokenCookie == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); + refreshTokenResponseDto.setAccessToken(accessToken); + return refreshTokenResponseDto; + } } From 25d9cfd201b57987352e88ad644263c3de92eef8 Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 20 Jan 2024 19:18:10 +0900 Subject: [PATCH 055/356] =?UTF-8?q?[Remove]=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C,=20=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomDefaultOAuth2UserService.java | 74 ---------- .../CustomMemberDetailsService.java | 41 ------ .../CustomTokenProviderService.java | 135 ------------------ .../config/security/SecurityConfig.java | 99 ------------- .../security/auth/OAuth2UserInfoFactory.java | 29 ---- .../config/security/auth/company/Kakao.java | 57 -------- ...SimpleUrlAuthenticationSuccessHandler.java | 91 ------------ .../token/CustomOncePerRequestFilter.java | 46 ------ 8 files changed, 572 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java delete mode 100644 src/main/java/com/ttubeog/global/config/security/SecurityConfig.java delete mode 100644 src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java delete mode 100644 src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java delete mode 100644 src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java delete mode 100644 src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java deleted file mode 100644 index d6891f08..00000000 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomDefaultOAuth2UserService.java +++ /dev/null @@ -1,74 +0,0 @@ -//package com.ttubeog.domain.auth.application; -// -//import com.ttubeog.domain.member.domain.Provider; -//import com.ttubeog.domain.member.domain.Role; -//import com.ttubeog.domain.member.domain.Member; -//import com.ttubeog.domain.member.domain.repository.MemberRepository; -//import com.ttubeog.global.DefaultAssert; -//import com.ttubeog.global.config.security.auth.OAuth2UserInfo; -//import com.ttubeog.global.config.security.token.UserPrincipal; -//import lombok.RequiredArgsConstructor; -//import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -//import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -//import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -//import org.springframework.security.oauth2.core.user.OAuth2User; -//import org.springframework.stereotype.Service; -// -//import java.util.Optional; -// -//@RequiredArgsConstructor -//@Service -//public class CustomDefaultOAuth2UserService extends DefaultOAuth2UserService { -// -// private final MemberRepository memberRepository; -// -// @Override -// public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException { -// OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest); -// try { -// return processOAuth2User(oAuth2UserRequest, oAuth2User); -// } catch (Exception e) { -// DefaultAssert.isAuthentication(e.getMessage()); -// } -// return null; -// } -// -// private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { -// OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); -// DefaultAssert.isAuthentication(!oAuth2UserInfo.getEmail().isEmpty()); -// -// Optional userOptional = memberRepository.findByEmail(oAuth2UserInfo.getEmail()); -// Member member; -// if (userOptional.isPresent()) { -// member = userOptional.get(); -// DefaultAssert.isAuthentication(member.getProvider().equals(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))); -// member = updateExistingMember(member, oAuth2UserInfo); -// } else { -// member = registerNewMember(oAuth2UserRequest, oAuth2UserInfo); -// } -// -// return UserPrincipal.create(member, oAuth2User.getAttributes()); -// } -// -// private Member registerNewMember(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { -// Member member = Member.builder() -// .provider(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())) -// .providerId(oAuth2UserInfo.getId()) -// .name(oAuth2UserInfo.getName()) -// .email(oAuth2UserInfo.getEmail()) -// .imageUrl(oAuth2UserInfo.getImageUrl()) -// .refreshToken(oAuth2UserInfo.getRefreshToken()) -// .role(Role.USER) -// .build(); -// -// return memberRepository.save(member); -// } -// -// private Member updateExistingMember(Member member, OAuth2UserInfo oAuth2UserInfo) { -// -// member.updateName(oAuth2UserInfo.getName()); -// member.updateImageUrl(oAuth2UserInfo.getImageUrl()); -// -// return memberRepository.save(member); -// } -//} diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java deleted file mode 100644 index a3a1ba82..00000000 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomMemberDetailsService.java +++ /dev/null @@ -1,41 +0,0 @@ -//package com.ttubeog.domain.auth.application; -// -//import com.ttubeog.domain.member.domain.Member; -//import com.ttubeog.domain.member.domain.repository.MemberRepository; -//import com.ttubeog.global.DefaultAssert; -//import com.ttubeog.global.config.security.token.UserPrincipal; -//import jakarta.transaction.Transactional; -//import lombok.RequiredArgsConstructor; -//import org.springframework.security.core.userdetails.UserDetails; -//import org.springframework.security.core.userdetails.UserDetailsService; -//import org.springframework.security.core.userdetails.UsernameNotFoundException; -//import org.springframework.stereotype.Service; -// -//import java.util.Optional; -// -//@RequiredArgsConstructor -//@Service -//public class CustomMemberDetailsService implements UserDetailsService{ -// -// private final MemberRepository memberRepository; -// -// @Override -// public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { -// -// Member member = memberRepository.findByEmail(email) -// .orElseThrow(() -> -// new UsernameNotFoundException("멤버 정보를 찾을 수 없습니다.") -// ); -// -// return UserPrincipal.create(member); -// } -// -// @Transactional -// public UserDetails loadUserById(Long id) { -// Optional user = memberRepository.findById(id); -// DefaultAssert.isOptionalPresent(user); -// -// return UserPrincipal.create(user.get()); -// } -// -//} diff --git a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java b/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java deleted file mode 100644 index 2cdd9324..00000000 --- a/src/main/java/com/ttubeog/domain/auth/application/CustomTokenProviderService.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.ttubeog.domain.auth.application; - -import com.ttubeog.domain.auth.dto.TokenMapping; -import com.ttubeog.global.config.security.OAuth2Config; -import com.ttubeog.global.config.security.token.UserPrincipal; -import io.jsonwebtoken.*; -import io.jsonwebtoken.io.Decoders; -import io.jsonwebtoken.security.Keys; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Service; - -import java.security.Key; -import java.util.Date; - -@Slf4j -@Service -public class CustomTokenProviderService { - - @Autowired - private OAuth2Config oAuth2Config; - -// @Autowired -// private CustomMemberDetailsService customMemberDetailsService; - - public TokenMapping refreshToken(Authentication authentication, String refreshToken) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - Date now = new Date(); - - Date accessTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getAccessTokenExpirationMsec()); - - String secretKey = oAuth2Config.getAuth().getTokenSecret(); - byte[] keyBytes = Decoders.BASE64.decode(secretKey); - Key key = Keys.hmacShaKeyFor(keyBytes); - - String accessToken = Jwts.builder() - .setSubject(Long.toString(userPrincipal.getId())) - .setIssuedAt(new Date()) - .setExpiration(accessTokenExpiresIn) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - - return TokenMapping.builder() - .userEmail(userPrincipal.getEmail()) - .accessToken(accessToken) - .refreshToken(refreshToken) - .build(); - } - - public TokenMapping createToken(Authentication authentication) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - - Date now = new Date(); - - Date accessTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getAccessTokenExpirationMsec()); - Date refreshTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getRefreshTokenExpirationMsec()); - - String secretKey = oAuth2Config.getAuth().getTokenSecret(); - - byte[] keyBytes = Decoders.BASE64.decode(secretKey); - Key key = Keys.hmacShaKeyFor(keyBytes); - - String accessToken = Jwts.builder() - .setSubject(Long.toString(userPrincipal.getId())) - .setIssuedAt(new Date()) - .setExpiration(accessTokenExpiresIn) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - - String refreshToken = Jwts.builder() - .setExpiration(refreshTokenExpiresIn) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - - return TokenMapping.builder() - .userEmail(userPrincipal.getEmail()) - .accessToken(accessToken) - .refreshToken(refreshToken) - .build(); - } - - public Long getUserIdFromToken(String token) { - Claims claims = Jwts.parserBuilder() - .setSigningKey(oAuth2Config.getAuth().getTokenSecret()) - .build() - .parseClaimsJws(token) - .getBody(); - - return Long.parseLong(claims.getSubject()); - } - -// public UsernamePasswordAuthenticationToken getAuthenticationById(String token){ -// Long userId = getUserIdFromToken(token); -// UserDetails userDetails = customMemberDetailsService.loadUserById(userId); -// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); -// return authentication; -// } -// -// public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String email){ -// UserDetails userDetails = customMemberDetailsService.loadUserByUsername(email); -// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); -// return authentication; -// } - - public Long getExpiration(String token) { - // accessToken 남은 유효시간 - Date expiration = Jwts.parserBuilder().setSigningKey(oAuth2Config.getAuth().getTokenSecret()).build().parseClaimsJws(token).getBody().getExpiration(); - // 현재 시간 - Long now = new Date().getTime(); - //시간 계산 - return (expiration.getTime() - now); - } - - public boolean validateToken(String token) { - try { - //log.info("bearerToken = {} \n oAuth2Config.getAuth()={}", token, oAuth2Config.getAuth().getTokenSecret()); - Jwts.parserBuilder().setSigningKey(oAuth2Config.getAuth().getTokenSecret()).build().parseClaimsJws(token); - return true; - } catch (io.jsonwebtoken.security.SecurityException ex) { - log.error("잘못된 JWT 서명입니다."); - } catch (MalformedJwtException ex) { - log.error("잘못된 JWT 서명입니다."); - } catch (ExpiredJwtException ex) { - log.error("만료된 JWT 토큰입니다."); - } catch (UnsupportedJwtException ex) { - log.error("지원되지 않는 JWT 토큰입니다."); - } catch (IllegalArgumentException ex) { - log.error("JWT 토큰이 잘못되었습니다."); - } - return false; - } -} diff --git a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java b/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java deleted file mode 100644 index f867fee3..00000000 --- a/src/main/java/com/ttubeog/global/config/security/SecurityConfig.java +++ /dev/null @@ -1,99 +0,0 @@ -//package com.ttubeog.global.config.security; -// -//import com.ttubeog.domain.auth.application.CustomDefaultOAuth2UserService; -//import com.ttubeog.domain.auth.application.CustomMemberDetailsService; -//import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; -//import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationFailureHandler; -//import com.ttubeog.global.config.security.handler.CustomSimpleUrlAuthenticationSuccessHandler; -//import com.ttubeog.global.config.security.token.CustomAuthenticationEntryPoint; -//import com.ttubeog.global.config.security.token.CustomOncePerRequestFilter; -//import lombok.RequiredArgsConstructor; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.security.authentication.AuthenticationManager; -//import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -//import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; -//import org.springframework.security.config.annotation.web.builders.HttpSecurity; -//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -//import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -//import org.springframework.security.config.http.SessionCreationPolicy; -//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -//import org.springframework.security.crypto.password.PasswordEncoder; -//import org.springframework.security.web.SecurityFilterChain; -//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -// -//import static org.springframework.security.config.Customizer.withDefaults; -// -// -//@RequiredArgsConstructor -//@Configuration -//@EnableWebSecurity -//public class SecurityConfig { -// -// private final CustomMemberDetailsService customMemberDetailsService; -// private final CustomDefaultOAuth2UserService customOAuth2UserService; -// private final CustomSimpleUrlAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; -// private final CustomSimpleUrlAuthenticationFailureHandler oAuth2AuthenticationFailureHandler; -// private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; -// -// @Bean -// public PasswordEncoder passwordEncoder() { -// return new BCryptPasswordEncoder(); -// } -// -// @Bean -// public CustomOncePerRequestFilter customOncePerRequestFilter() { -// return new CustomOncePerRequestFilter(); -// } -// -// @Bean -// public DaoAuthenticationProvider authenticationProvider() { -// DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); -// -// authenticationProvider.setUserDetailsService(customMemberDetailsService); -// authenticationProvider.setPasswordEncoder(passwordEncoder()); -// -// return authenticationProvider; -// } -// -// @Bean -// public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { -// return authenticationConfiguration.getAuthenticationManager(); -// } -// -// @Bean -// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { -// http -// .cors(withDefaults()) -// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) -// .csrf(AbstractHttpConfigurer::disable) -// .formLogin(AbstractHttpConfigurer::disable) -// .httpBasic(AbstractHttpConfigurer::disable) -// .exceptionHandling(exception -> exception.authenticationEntryPoint(new CustomAuthenticationEntryPoint())) -// .authorizeHttpRequests(authorize -> authorize -// .requestMatchers("/", "/error", "/favicon.ico", "/**/*.png", "/**/*.gif", "/**/*.svg", "/**/*.jpg", "/**/*.html", "/**/*.css", "/**/*.js") -// .permitAll() -// .requestMatchers("/swagger", "/swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**", "/v3/api-docs/**") -// .permitAll() -// .requestMatchers("/login/**","/auth/**", "/oauth2/**") -// .permitAll() -// .requestMatchers("/blog/**") -// .permitAll() -// .anyRequest() -// .authenticated()) -// .oauth2Login(oauth2 -> oauth2 -// .authorizationEndpoint(authorization -> authorization -// .baseUri("/oauth2/authorize") -// .authorizationRequestRepository(customAuthorizationRequestRepository)) -// .redirectionEndpoint(redirection -> redirection -// .baseUri("/oauth2/callback/**")) -// .userInfoEndpoint(userInfo -> userInfo -// .userService(customOAuth2UserService)) -// .successHandler(oAuth2AuthenticationSuccessHandler) -// .failureHandler(oAuth2AuthenticationFailureHandler)); -// -// http.addFilterBefore(customOncePerRequestFilter(), UsernamePasswordAuthenticationFilter.class); -// return http.build(); -// } -// -//} diff --git a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java b/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java deleted file mode 100644 index d0190425..00000000 --- a/src/main/java/com/ttubeog/global/config/security/auth/OAuth2UserInfoFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -//package com.ttubeog.global.config.security.auth; -// -//import com.ttubeog.domain.member.domain.Provider; -//import com.ttubeog.global.DefaultAssert; -//import com.ttubeog.global.config.security.auth.company.Kakao; -// -//import java.util.Map; -// -//public class OAuth2UserInfoFactory { -// public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { -//// if(registrationId.equalsIgnoreCase(Provider.google.toString())) { -//// return new Google(attributes); -//// } else if (registrationId.equalsIgnoreCase(Provider.facebook.toString())) { -//// return new Facebook(attributes); -//// } else if (registrationId.equalsIgnoreCase(Provider.github.toString())) { -//// return new Github(attributes); -//// } else if (registrationId.equalsIgnoreCase(Provider.naver.toString())) { -//// return new Naver(attributes); -//// } else if ~~ -// if (registrationId.equalsIgnoreCase(Provider.kakao.toString())) { -// return new Kakao(attributes); -// } else if (registrationId.equalsIgnoreCase(Provider.apple.toString())) { -// DefaultAssert.isAuthentication("애플 로그인은 구현 예정입니다."); -// } else { -// DefaultAssert.isAuthentication("해당 oauth2 기능은 지원하지 않습니다."); -// } -// return null; -// } -//} diff --git a/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java b/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java deleted file mode 100644 index ccf5f01b..00000000 --- a/src/main/java/com/ttubeog/global/config/security/auth/company/Kakao.java +++ /dev/null @@ -1,57 +0,0 @@ -//package com.ttubeog.global.config.security.auth.company; -// -//import com.ttubeog.domain.member.domain.Provider; -//import com.ttubeog.global.config.security.auth.OAuth2UserInfo; -// -//import java.util.Map; -// -//public class Kakao extends OAuth2UserInfo { -// -// public Kakao(Map attributes) { -// super(attributes); -// } -// -// @Override -// public String getId() { -// return attributes.get("id").toString(); -// } -// -// @Override -// public String getName() { -// Map properties = (Map) attributes.get("properties"); -// -// if (properties == null) { -// return null; -// } -// -// return (String) properties.get("nickname"); -// } -// -// @Override -// public String getEmail() { -// Map properties = (Map) attributes.get("kakao_account"); -// if (properties == null) { -// return null; -// } -// return (String) properties.get("email"); -// } -// -// @Override -// public String getImageUrl() { -// Map properties = (Map) attributes.get("properties"); -// -// if (properties == null) { -// return null; -// } -// -// return (String) properties.get("thumbnail_image"); -// } -// -// @Override -// public String getProvider(){ -// return Provider.kakao.toString(); -// } -// -// @Override -// public String getRefreshToken() { return} -//} diff --git a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java b/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java deleted file mode 100644 index cb9d066c..00000000 --- a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.ttubeog.global.config.security.handler; - -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.OAuth2Config; -import com.ttubeog.global.config.security.util.CustomCookie; -import com.ttubeog.domain.auth.domain.Token; -import com.ttubeog.domain.auth.dto.TokenMapping; -import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; -import com.ttubeog.domain.auth.domain.repository.TokenRepository; -import com.ttubeog.domain.auth.application.CustomTokenProviderService; - -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import lombok.RequiredArgsConstructor; - -import static com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository.REDIRECT_URI_PARAM_COOKIE_NAME; - -import java.io.IOException; -import java.net.URI; -import java.util.Optional; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -@RequiredArgsConstructor -@Component -public class CustomSimpleUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{ - - private final CustomTokenProviderService customTokenProviderService; - private final OAuth2Config oAuth2Config; - private final TokenRepository tokenRepository; - private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - DefaultAssert.isAuthentication(!response.isCommitted()); - - String targetUrl = determineTargetUrl(request, response, authentication); - - TokenMapping tokenMapping = customTokenProviderService.createToken(authentication); - CustomCookie.addCookie(response, "Authorization", "Bearer_" + tokenMapping.getAccessToken(), (int) oAuth2Config.getAuth().getAccessTokenExpirationMsec()); - CustomCookie.addCookie(response, "Refresh_Token", "Bearer_" + tokenMapping.getRefreshToken(), (int) oAuth2Config.getAuth().getRefreshTokenExpirationMsec()); - - clearAuthenticationAttributes(request, response); - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } - - protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - Optional redirectUri = CustomCookie.getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME).map(Cookie::getValue); - - DefaultAssert.isAuthentication( !(redirectUri.isPresent() && !isAuthorizedRedirectUri(redirectUri.get())) ); - - String targetUrl = redirectUri.orElse(getDefaultTargetUrl()); - - TokenMapping tokenMapping = customTokenProviderService.createToken(authentication); - Token token = Token.builder() - .userEmail(tokenMapping.getUserEmail()) - .refreshToken(tokenMapping.getRefreshToken()) - .build(); - tokenRepository.save(token); - - return UriComponentsBuilder.fromUriString(targetUrl) - .queryParam("token", tokenMapping.getAccessToken()) - .build().toUriString(); - } - - protected void clearAuthenticationAttributes(HttpServletRequest request, HttpServletResponse response) { - super.clearAuthenticationAttributes(request); - customAuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response); - } - - private boolean isAuthorizedRedirectUri(String uri) { - URI clientRedirectUri = URI.create(uri); - - return oAuth2Config.getOauth2().getAuthorizedRedirectUris() - .stream() - .anyMatch(authorizedRedirectUri -> { - URI authorizedURI = URI.create(authorizedRedirectUri); - if(authorizedURI.getHost().equalsIgnoreCase(clientRedirectUri.getHost()) - && authorizedURI.getPort() == clientRedirectUri.getPort()) { - return true; - } - return false; - }); - } -} diff --git a/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java b/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java deleted file mode 100644 index dea31ffe..00000000 --- a/src/main/java/com/ttubeog/global/config/security/token/CustomOncePerRequestFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -//package com.ttubeog.global.config.security.token; -// -//import com.ttubeog.domain.auth.application.CustomTokenProviderService; -//import jakarta.servlet.FilterChain; -//import jakarta.servlet.ServletException; -//import jakarta.servlet.http.HttpServletRequest; -//import jakarta.servlet.http.HttpServletResponse; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -//import org.springframework.security.core.context.SecurityContextHolder; -//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -//import org.springframework.util.StringUtils; -//import org.springframework.web.filter.OncePerRequestFilter; -// -//import java.io.IOException; -// -//@Slf4j -//public class CustomOncePerRequestFilter extends OncePerRequestFilter{ -// -//// @Autowired -//// private CustomTokenProviderService customTokenProviderService; -// -// @Override -// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { -// String jwt = getJwtFromRequest(request); -// -//// if (StringUtils.hasText(jwt) && customTokenProviderService.validateToken(jwt)) { -//// UsernamePasswordAuthenticationToken authentication = customTokenProviderService.getAuthenticationById(jwt); -//// authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); -//// SecurityContextHolder.getContext().setAuthentication(authentication); -//// } -// -// filterChain.doFilter(request, response); -// } -// -// private String getJwtFromRequest(HttpServletRequest request) { -// String bearerToken = request.getHeader("Authorization"); -// if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer")) { -// log.info("bearerToken = {}", bearerToken.substring(7, bearerToken.length())); -// return bearerToken.substring(7, bearerToken.length()); -// } -// return null; -// } -// -//} From 915bdad13580ee8d1c9fccf1334aa48c2ab095d8 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 20 Jan 2024 22:10:51 +0900 Subject: [PATCH 056/356] =?UTF-8?q?[Feat]=20=EC=8B=9C=EA=B0=84=EB=A7=88?= =?UTF-8?q?=EB=8B=A4=20=ED=98=9C=ED=83=9D=20=EC=82=AC=EC=9A=A9=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 멤버가 혜택을 저장한지 1달이 지났다면 만료기간 지남 체크 1시간마다 체크(임시) --- .../java/com/ttubeog/TtubeogApplication.java | 2 ++ .../benefit/application/BenefitService.java | 25 ++++++++++++++++--- .../domain/benefit/domain/MemberBenefit.java | 4 +++ .../repository/MemberBenefitRepository.java | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/TtubeogApplication.java b/src/main/java/com/ttubeog/TtubeogApplication.java index 718b5355..414bf6f4 100644 --- a/src/main/java/com/ttubeog/TtubeogApplication.java +++ b/src/main/java/com/ttubeog/TtubeogApplication.java @@ -4,8 +4,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.PropertySource; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling @PropertySource(value = {"classpath:database/application-database.yml"}, factory = YamlPropertySourceFactory.class) @PropertySource(value = { "classpath:oauth2/application-oauth2.yml" }, factory = YamlPropertySourceFactory.class) @PropertySource(value = { "classpath:swagger/application-springdoc.yml" }, factory = YamlPropertySourceFactory.class) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 88bc22e5..f18f5e62 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -25,6 +25,7 @@ import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,6 +50,8 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi // Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); + //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 + Benefit benefit = Benefit.builder() .content(createBenefitReq.getContent()) .type(createBenefitReq.getType()) @@ -79,6 +82,8 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); + //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 + benefitRepository.delete(benefit); ApiResponse apiResponse = ApiResponse.builder() @@ -93,10 +98,10 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit @Transactional public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); - //TODO userOptional과 benefit의 userId가 일치하는지 확인 + //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 benefit.updateContent(updateBenefitReq.getContent()); @@ -195,5 +200,19 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) return ResponseEntity.ok(apiResponse); } - //TODO 한달지나면 has_expired true로 만들기 + //한달지나면 expired true로 만들기 + @Transactional + @Scheduled(fixedRate = 60*60000) //1시간마다 검사 + public void autoCheckFrozen() { + System.out.println("혜택 유효기간 체크"); + List memberBenefitList = memberBenefitRepository.findAllByExpiredFalse(); + + if (!memberBenefitList.isEmpty()) { + for (MemberBenefit memberBenefit : memberBenefitList) { + if (memberBenefit.getCreatedAt().isBefore(LocalDateTime.now().minusMonths(1))) { + memberBenefit.terminateBenefit(); + } + } + } + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java index 15689099..17730f2b 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java @@ -41,4 +41,8 @@ public MemberBenefit(Long id, Member member, Benefit benefit, Boolean used, Bool public void useBenefit() { this.used = true; } + + public void terminateBenefit() { + this.expired = true; + } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 1e9bdc94..6cb68dee 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -17,4 +17,5 @@ public interface MemberBenefitRepository extends JpaRepository findByBenefitAndMemberAndExpiredIsFalse(Benefit benefit, Member member); + List findAllByExpiredFalse(); } From c055c84ce11605e9b452ae8864705d1668f89a7a Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 20 Jan 2024 23:58:18 +0900 Subject: [PATCH 057/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=ED=98=9C=ED=83=9D?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10개 기준으로 페이지 나누어서 내가 보유한 혜택을 조회하는 api입니다. 사용 가능, 사용 완료, 만료 혜택을 모두 조회합니다. --- .../benefit/application/BenefitService.java | 32 ++++++++++++++++++- .../repository/MemberBenefitRepository.java | 4 +++ .../presentation/BenefitController.java | 16 ++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index f18f5e62..69c9f6e0 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -24,6 +24,8 @@ import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -200,10 +202,38 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) return ResponseEntity.ok(apiResponse); } + //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) + public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page) throws JsonProcessingException { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Page memberBenefitPage = memberBenefitRepository.findAllByMember(member, PageRequest.of(page, 10)); + + List saveBenefitRes = memberBenefitPage.stream().map( + memberBenefit -> SaveBenefitRes.builder() + .id(memberBenefit.getId()) + .benefitId(memberBenefit.getBenefit().getId()) +// .store(memberBenefit.getStore().getId()) + .used(memberBenefit.getUsed()) + .expried(memberBenefit.getExpired()) + .createdAt(memberBenefit.getCreatedAt()) + .content(memberBenefit.getBenefit().getContent()) + .type(memberBenefit.getBenefit().getType()) + .build() + ).toList(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(saveBenefitRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + //한달지나면 expired true로 만들기 @Transactional @Scheduled(fixedRate = 60*60000) //1시간마다 검사 - public void autoCheckFrozen() { + public void autoCheckExpired() { System.out.println("혜택 유효기간 체크"); List memberBenefitList = memberBenefitRepository.findAllByExpiredFalse(); diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 6cb68dee..9761a672 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -3,6 +3,8 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.member.domain.Member; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -18,4 +20,6 @@ public interface MemberBenefitRepository extends JpaRepository findByBenefitAndMemberAndExpiredIsFalse(Benefit benefit, Member member); List findAllByExpiredFalse(); + + Page findAllByMember(Member member, PageRequest pageRequest); } diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 5452525d..84ca8ab8 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -13,6 +13,7 @@ import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -105,4 +106,19 @@ public ResponseEntity useBenefit( ) throws JsonProcessingException { return benefitService.useBenefit(userPrincipal, benefitId); } + + //혜택 조회 + @Operation(summary = "혜택 조회", description = "멤버가 보유 중인 혜택을 모두 조회합니다. 페이지 번호 0번이 첫 번째 페이지 입니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "혜택 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "혜택 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @GetMapping + public ResponseEntity findMyBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "page") Integer page + ) throws JsonProcessingException { + return benefitService.findMyBenefit(userPrincipal, page); + } } From 7029945b89397c85be06b6c5c141e18c3d9d693a Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 21 Jan 2024 00:03:52 +0900 Subject: [PATCH 058/356] =?UTF-8?q?[Chore]=20build.gradle=20=EC=9B=90?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트용 MariaDB 사용하던 것을 원상태로 복구하는걸 깜빡했습니다 --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 05608c45..f746ce27 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" -// runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' From 4ae4a3fba94cb2e7e69b414755ec0c7290753010 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 21 Jan 2024 08:18:48 +0900 Subject: [PATCH 059/356] =?UTF-8?q?[Feat]=20Game=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++- .../domain/game/domain/BasketballGame.java | 25 ++++++++++++++++-- .../com/ttubeog/domain/game/domain/Game.java | 17 ++++++++---- .../ttubeog/domain/game/domain/GameType.java | 5 ++++ .../ttubeog/domain/game/domain/GiftGame.java | 24 +++++++++++++++-- .../domain/game/domain/RouletteGame.java | 26 +++++++++++++++++-- .../domain/game/domain/RouletteOption.java | 22 ++++++++++++++-- 7 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/domain/GameType.java diff --git a/build.gradle b/build.gradle index f746ce27..05608c45 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" - runtimeOnly 'com.mysql:mysql-connector-j' +// runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index 79fabbcb..b1e56474 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -1,6 +1,27 @@ package com.ttubeog.domain.game.domain; -import com.ttubeog.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; -public class BasketballGame extends BaseEntity { +import java.time.LocalDateTime; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@Table(name = "basketball_game") +public class BasketballGame { + + @Id + @OneToOne + @MapsId + @JoinColumn(name = "game_id") + private Game game; + + private LocalDateTime timeLimit; + + private Integer ballCount; + + private Integer successCount; } diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index a9bca572..7b82967f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -1,15 +1,22 @@ package com.ttubeog.domain.game.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter @Entity -public class Game extends BaseEntity { +@Table(name = "game") +public abstract class Game extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private GameType type; } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GameType.java b/src/main/java/com/ttubeog/domain/game/domain/GameType.java new file mode 100644 index 00000000..47678acf --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/domain/GameType.java @@ -0,0 +1,5 @@ +package com.ttubeog.domain.game.domain; + +public enum GameType { + basketball, roulette, gift +} diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index 238fbdf6..d1f6b09f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -1,6 +1,26 @@ package com.ttubeog.domain.game.domain; -import com.ttubeog.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@Table(name = "gift_game") +public class GiftGame { + + @Id + @OneToOne + @MapsId + @JoinColumn(name = "game_id") + private Game game; + + private LocalDateTime timeLimit; + + private Integer giftCount; -public class GiftGame extends BaseEntity { } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index c0c06607..48354d64 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -1,6 +1,28 @@ package com.ttubeog.domain.game.domain; -import com.ttubeog.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@Table(name = "roulette_game") +public class RouletteGame { + + @Id + @OneToOne + @MapsId + @JoinColumn(name = "game_id") + private Game game; + + private int optionCount; + + // 연관 관계 매핑 + @OneToMany(mappedBy = "rouletteGame") + private List options; -public class RouletteGame extends BaseEntity { } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java index 769d4e5a..481e6d20 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java @@ -1,6 +1,24 @@ package com.ttubeog.domain.game.domain; -import com.ttubeog.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@Table(name = "roulette_option") +public class RouletteOption { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long optionId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "roulette_game_id") + private RouletteGame rouletteGame; + + private String content; -public class RouletteOption extends BaseEntity { } From d813cb6239ec58cd891b64a5ca20d7862bec02db Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 21 Jan 2024 13:16:30 +0900 Subject: [PATCH 060/356] =?UTF-8?q?[Fix]=20JWT=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EC=8A=A4=EC=9B=A8=EA=B1=B0=EC=97=90=EC=84=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 8 +++- .../auth/controller/OauthController.java | 42 +++++++++--------- .../auth/exception/CustomException.java | 16 +++++++ .../domain/auth/exception/ErrorCode.java | 27 ++++++++++++ .../domain/auth/exception/ErrorResponse.java | 16 +++++++ .../exception/ExceptionHandlerFilter.java | 38 ++++++++++++++++ .../exception/GlobalExceptionHandler.java | 40 +++++++++++++++++ .../ttubeog/domain/auth/filter/JwtFilter.java | 44 +++++++++++++------ .../domain/auth/service/OauthService.java | 29 ++++++------ 9 files changed, 210 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/CustomException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 28ae461a..d97d376e 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,8 +1,10 @@ package com.ttubeog.domain.auth.config; +import com.ttubeog.domain.auth.exception.ExceptionHandlerFilter; import com.ttubeog.domain.auth.service.JwtTokenService; import com.ttubeog.domain.auth.filter.JwtFilter; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.domain.MemberRole; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,11 +37,14 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .csrf((csrf) -> csrf.disable()) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/auth/login/**").permitAll() + .requestMatchers("/swagger-ui/**", "/v3/api-docs", "/swagger-resources/**").permitAll() + .requestMatchers("/user/**").hasAuthority(MemberRole.USER.getRole()) .anyRequest().authenticated()) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable()) // 기본 http 미사용 .addFilterBefore(new JwtFilter(jwtTokenService, memberService), UsernamePasswordAuthenticationFilter.class) // JWT 필터 추가 + .addFilterBefore(new ExceptionHandlerFilter(), JwtFilter.class) // Security Filter 에서 CustomException 사용하기 위해 추가 .build(); } @@ -47,6 +52,7 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc public WebSecurityCustomizer webSecurityCustomizer(){ return web -> web.ignoring() - .requestMatchers("/auth/login/**"); + .requestMatchers("/auth/login/**") + .requestMatchers("/swagger-ui/**", "/v2/api-docs", "/swagger-resources/**"); } } diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 198d77a9..283cd363 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -37,25 +37,25 @@ public OauthResponseDto loginWithKaKao( return oauthResponseDto; } - // 리프레시 토큰으로 액세스토큰 재발급 - @PostMapping("/token/refresh") - public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { - RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); - Cookie[] list = request.getCookies(); - - if (list == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); - } - - Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> - cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); - - if (refreshTokenCookie == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); - } - - String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); - refreshTokenResponseDto.setAccessToken(accessToken); - return refreshTokenResponseDto; - } +// // 리프레시 토큰으로 액세스토큰 재발급 +// @PostMapping("/token/refresh") +// public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { +// RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); +// Cookie[] list = request.getCookies(); +// +// if (list == null) { +// throw new DefaultException(ErrorCode.INVALID_CHECK); +// } +// +// Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> +// cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); +// +// if (refreshTokenCookie == null) { +// throw new DefaultException(ErrorCode.INVALID_CHECK); +// } +// +// String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); +// refreshTokenResponseDto.setAccessToken(accessToken); +// return refreshTokenResponseDto; +// } } diff --git a/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java b/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java new file mode 100644 index 00000000..fa142b3b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java @@ -0,0 +1,16 @@ +package com.ttubeog.domain.auth.exception; + + +public class CustomException extends RuntimeException { + + private final ErrorCode errorCode; + + public CustomException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public ErrorCode getErrorCode() { + return errorCode; + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java new file mode 100644 index 00000000..7fa0a68e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java @@ -0,0 +1,27 @@ +package com.ttubeog.domain.auth.exception; + +import org.springframework.http.HttpStatus; + +public enum ErrorCode { + UNAUTHORIZED("인증되지 않은 요청입니다.", HttpStatus.UNAUTHORIZED), + INVALID_ACCESS_TOKEN("유효하지 않은 액세스 토큰입니다.", HttpStatus.UNAUTHORIZED), + INVALID_REFRESH_TOKEN("유효하지 않은 리프레시 토큰입니다.", HttpStatus.UNAUTHORIZED), + BAD_REQUEST("잘못된 요청입니다.", HttpStatus.BAD_REQUEST), + NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED); + + private final String message; + private final HttpStatus httpStatus; + + ErrorCode(String message, HttpStatus httpStatus) { + this.message = message; + this.httpStatus = httpStatus; + } + + public String getMessage() { + return message; + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java new file mode 100644 index 00000000..f73cc962 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java @@ -0,0 +1,16 @@ +package com.ttubeog.domain.auth.exception; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.*; + +@Getter +@AllArgsConstructor +public class ErrorResponse { + private static final ObjectMapper objectMapper = new ObjectMapper(); + private String errMsg; + + public String convertToJson() throws JsonProcessingException { + return objectMapper.writeValueAsString(this); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java b/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java new file mode 100644 index 00000000..c6757df1 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java @@ -0,0 +1,38 @@ +package com.ttubeog.domain.auth.exception; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +public class ExceptionHandlerFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + try { + filterChain.doFilter(request, response); + } catch (CustomException ex) { + setErrorResponse(ex.getErrorCode().getHttpStatus(), response, ex); + } catch (Exception ex) { + setErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, response, ex); + } + } + + public void setErrorResponse(HttpStatus status, HttpServletResponse response, Throwable ex) throws IOException { + logger.error("[ExceptionHandlerFilter] errMsg : " + ex.getMessage()); + + response.setStatus(status.value()); + response.setContentType("application/json; charset=UTF-8"); + + response.getWriter().write( + new ErrorResponse(ex.getMessage()) + .convertToJson() + ); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java b/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..145fbc34 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java @@ -0,0 +1,40 @@ +package com.ttubeog.domain.auth.exception; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + @ExceptionHandler(CustomException.class) + public ResponseEntity handleCustomException(CustomException ex) { + logger.error("[CustomException] errCode : " + ex.getErrorCode()); + logger.error("[CustomException] errMsg : " + ex.getMessage()); + return new ResponseEntity( + new ErrorResponse(ex.getMessage()), + ex.getErrorCode().getHttpStatus() + ); + } + + @ExceptionHandler(RuntimeException.class) + public ResponseEntity handleRuntimeException(RuntimeException ex) { + logger.error("[RuntimeException] errMsg : " + ex.getMessage()); + return new ResponseEntity( + new ErrorResponse(ex.getMessage()), + HttpStatus.INTERNAL_SERVER_ERROR + ); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(RuntimeException ex) { + logger.error("[Exception] errMsg : " + ex.getMessage()); + return new ResponseEntity( + new ErrorResponse(ex.getMessage()), + HttpStatus.INTERNAL_SERVER_ERROR + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index ba591801..47dacfc8 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -1,11 +1,11 @@ package com.ttubeog.domain.auth.filter; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.auth.service.JwtTokenService; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.global.config.security.token.UserPrincipal; -import com.ttubeog.global.error.DefaultException; -import com.ttubeog.global.payload.ErrorCode; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; @@ -31,19 +31,35 @@ public class JwtFilter extends GenericFilterBean { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); - String jwt = resolveToken(httpServletRequest); - if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { - Long memberId = Long.valueOf(jwtTokenService.getPayload(jwt)); - MemberDto member = memberService.findById(memberId); - if (member == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); + try { + String jwt = resolveToken(httpServletRequest); + + if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { + Long userId = Long.valueOf(jwtTokenService.getPayload(jwt)); // 토큰에 있는 userId 가져오기 + MemberDto user = memberService.findById(userId); // userId로 + if (user == null) { + throw new CustomException(ErrorCode.NOT_EXIST_USER); + } + UserDetails userDetails = UserPrincipal.create(user); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + } else { + throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); + } + } catch (CustomException ex) { + // 스웨거에 대한 예외 처리 + if (httpServletRequest.getRequestURI().contains("/swagger") || httpServletRequest.getRequestURI().contains("/v2/api-docs")) { + // 여기에서 스웨거 예외 처리 로직을 추가 + // 예를 들어, HttpServletResponse에 적절한 응답을 설정하거나 다른 방식으로 처리 + // 아래는 예시 코드이므로 필요에 따라 수정이 필요합니다. + servletResponse.getWriter().write("Swagger access exception: " + ex.getMessage()); + servletResponse.getWriter().flush(); + servletResponse.getWriter().close(); + return; + } else { + throw ex; // 스웨거 이외의 경우에는 예외를 다시 던집니다. } - UserDetails memberDetails = UserPrincipal.create(member); - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(memberDetails, null, memberDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - } else { - throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); } filterChain.doFilter(servletRequest, servletResponse); @@ -57,6 +73,6 @@ private String resolveToken(HttpServletRequest servletRequest) { return bearerToken.substring(7); } - return null; + return ""; } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 188068f5..64bab2a8 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -30,21 +30,22 @@ public String getTokens(Long id, HttpServletResponse response) { memberDto.setRefreshToken(refreshToken); memberService.updateRefreshToken(memberDto); + jwtTokenService.addRefreshTokenToCookie(refreshToken, response); return accessToken; } - // 리프레시 토큰을 액세스 토큰으로 갱신 - public String refreshToAccessToken(String refreshToken) { - MemberDto memberDto = memberService.findByRefreshToken(refreshToken); - - if(memberDto == null) { - throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); - } - - if (!jwtTokenService.validateToken(refreshToken)) { - throw new DefaultException(ErrorCode.INVALID_CHECK); - } - - return jwtTokenService.createAccessToken(memberDto.getId().toString()); - } +// // 리프레시 토큰을 액세스 토큰으로 갱신 +// public String refreshToAccessToken(String refreshToken) { +// MemberDto memberDto = memberService.findByRefreshToken(refreshToken); +// +// if(memberDto == null) { +// throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); +// } +// +// if (!jwtTokenService.validateToken(refreshToken)) { +// throw new DefaultException(ErrorCode.INVALID_CHECK); +// } +// +// return jwtTokenService.createAccessToken(memberDto.getId().toString()); +// } } From 394980b08812ffbf9a51a4af7804885f743d4569 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 21 Jan 2024 13:39:23 +0900 Subject: [PATCH 061/356] =?UTF-8?q?[Fix]=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 에러 해결 --- .../ttubeog/domain/auth/filter/JwtFilter.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 47dacfc8..52fce8ef 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -26,53 +26,53 @@ public class JwtFilter extends GenericFilterBean { private final JwtTokenService jwtTokenService; private final MemberService memberService; - // 액세스 토큰이 유효한지 확인하고 SecurityContext에 계정 정보를 저장 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; - logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); + + // Swagger UI 및 관련 리소스 경로에 대한 요청인 경우 토큰 검증 생략 + if (isSwaggerPath(httpServletRequest.getRequestURI())) { + filterChain.doFilter(servletRequest, servletResponse); + return; + } try { String jwt = resolveToken(httpServletRequest); - if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { - Long userId = Long.valueOf(jwtTokenService.getPayload(jwt)); // 토큰에 있는 userId 가져오기 - MemberDto user = memberService.findById(userId); // userId로 - if (user == null) { - throw new CustomException(ErrorCode.NOT_EXIST_USER); - } - UserDetails userDetails = UserPrincipal.create(user); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - } else { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); + authenticateWithJwtToken(jwt); } } catch (CustomException ex) { - // 스웨거에 대한 예외 처리 - if (httpServletRequest.getRequestURI().contains("/swagger") || httpServletRequest.getRequestURI().contains("/v2/api-docs")) { - // 여기에서 스웨거 예외 처리 로직을 추가 - // 예를 들어, HttpServletResponse에 적절한 응답을 설정하거나 다른 방식으로 처리 - // 아래는 예시 코드이므로 필요에 따라 수정이 필요합니다. - servletResponse.getWriter().write("Swagger access exception: " + ex.getMessage()); - servletResponse.getWriter().flush(); - servletResponse.getWriter().close(); - return; - } else { - throw ex; // 스웨거 이외의 경우에는 예외를 다시 던집니다. - } + // JWT 검증 실패 시 예외 처리 + throw ex; } filterChain.doFilter(servletRequest, servletResponse); } - // 헤더에서 액세스 토큰 가져오는 코드 - private String resolveToken(HttpServletRequest servletRequest) { - String bearerToken = servletRequest.getHeader(AUTHORIZATION_HEADER); + private boolean isSwaggerPath(String uri) { + return uri.contains("/swagger") || + uri.contains("/v3/api-docs") || + uri.contains("/swagger-resources") || + uri.contains("/swagger-ui.html") || + uri.contains("/webjars/"); + } + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } + return null; + } - return ""; + private void authenticateWithJwtToken(String jwt) { + Long userId = Long.valueOf(jwtTokenService.getPayload(jwt)); + MemberDto user = memberService.findById(userId); + if (user == null) { + throw new CustomException(ErrorCode.NOT_EXIST_USER); + } + UserDetails userDetails = UserPrincipal.create(user); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); } } From 516a540403f35b2ee442f27d8c6acdb0cffcd138 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 21 Jan 2024 13:48:45 +0900 Subject: [PATCH 062/356] =?UTF-8?q?[Feat]=20Comment=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 63 ++++++++++++++++++- .../comment/dto/request/GetCommentReq.java | 15 +++++ .../comment/dto/response/GetCommentRes.java | 30 +++++++++ .../presentation/CommentController.java | 28 ++++++--- 4 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 367e2fef..150d0a43 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -2,8 +2,10 @@ import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; +import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.domain.member.domain.Member; @@ -13,12 +15,17 @@ import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.apache.catalina.User; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import static java.lang.Math.abs; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -111,6 +118,60 @@ public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long comment return ResponseEntity.ok(apiResponse); } - // 댓글 조회 + public List getAllComments() { + return commentRepository.findAll(); + } + + // AR뷰를 위한 댓글 조회 + public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { + + Float userLatitude = getCommentReq.getLatitude(); + Float userLongitude = getCommentReq.getLongitude(); + + List allComments = getAllComments(); + Double radius = 20.0; // 반경값 확인 필요 + List showComments = new ArrayList<>(); + + for (Comment comment : allComments) { + Float commentLatitude = comment.getLatitude(); + Float commentLongitude = comment.getLongitude(); + + double distance = calculateDistance(userLatitude, userLongitude, commentLatitude, commentLongitude); + + if (distance < radius) { + GetCommentRes getCommentRes = GetCommentRes.builder() + .commentId(comment.getId()) + .memberId(comment.getMember().getId()) + .content(comment.getContent()) + .distance(distance) + .build(); + + showComments.add(getCommentRes); + } + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(showComments) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + // 거리 계산 + private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + double R = 6371; // 지구 반지름 + + double dLat = Math.toRadians(lat2 - lat1); + double dLon = Math.toRadians(lon2 - lon1); + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 단위 km + + return R * c; + } } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java new file mode 100644 index 00000000..5c16e981 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.comment.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetCommentReq { + + @Schema(description = "사용자 위치 위도값") + private Float latitude; + + @Schema(description = "사용자 위치 경도값") + private Float longitude; + +} diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java new file mode 100644 index 00000000..e4c7ca9e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java @@ -0,0 +1,30 @@ +package com.ttubeog.domain.comment.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class GetCommentRes { + + @Schema(description = "댓글 ID") + private Long commentId; + + @Schema(description = "작성자 ID") + private Long memberId; + + @Schema(description = "내용") + private String content; + + @Schema(description = "사용자와 해당 댓글 간 거리") + private Double distance; + + @Builder + public GetCommentRes(Long commentId, Long memberId, String content, Double distance) { + this.commentId = commentId; + this.memberId = memberId; + this.content = content; + this.distance = distance; + } + +} diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index cfd84fef..f214e68a 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.comment.presentation; import com.ttubeog.domain.comment.application.CommentService; +import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; @@ -21,6 +22,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + @Tag(name = "Comment", description = "Comment API") @RestController @RequiredArgsConstructor @@ -32,8 +35,8 @@ public class CommentController { // 댓글 작성 @Operation(summary = "댓글 작성", description = "댓글을 작성합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = WriteCommentRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = WriteCommentRes.class))}), + @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping public ResponseEntity writeComment( @@ -46,8 +49,8 @@ public ResponseEntity writeComment( // 댓글 수정 @Operation(summary = "댓글 수정", description = "댓글 내용을 수정합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateCommentRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateCommentRes.class))}), + @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PatchMapping public ResponseEntity updateComment( @@ -60,8 +63,8 @@ public ResponseEntity updateComment( // 댓글 삭제 @Operation(summary = "댓글 삭제", description = "댓글을 삭제합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @DeleteMapping("/{commentId}") public ResponseEntity deleteComment( @@ -71,5 +74,16 @@ public ResponseEntity deleteComment( return commentService.deleteComment(userPrincipal, commentId); } - // 댓글 조회 + // AR뷰 댓글 조회 (반경 이용) + @Operation(summary = "댓글 조회", description = "반경 내의 댓글을 조회힙니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = List.class))}), + @ApiResponse(responseCode = "400", description = "댓글 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping + public ResponseEntity getCommentForAR( + @Valid @RequestBody GetCommentReq getCommentReq + ) { + return commentService.getCommentForAR(getCommentReq); + } } From 3b429f757283b18ed1055798aa37bbd610a6d12f Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 21 Jan 2024 14:32:29 +0900 Subject: [PATCH 063/356] =?UTF-8?q?[Remove]=20=EB=A6=AC=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EA=B5=AC=ED=98=84=EB=B6=80=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=ED=95=B4=EC=A0=9C=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/OauthController.java | 44 ++++++++++--------- .../domain/auth/service/OauthService.java | 28 ++++++------ .../ttubeog/global/config/SwaggerConfig.java | 4 +- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 283cd363..ad472190 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -6,6 +6,7 @@ import com.ttubeog.domain.auth.service.OauthService; import com.ttubeog.global.error.DefaultException; import com.ttubeog.global.payload.ErrorCode; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -18,6 +19,7 @@ import java.util.Arrays; import java.util.stream.Collectors; +@Tag(name = "Oauth", description = "Oauth API") @RestController @RequiredArgsConstructor @RequestMapping("/auth") @@ -37,25 +39,25 @@ public OauthResponseDto loginWithKaKao( return oauthResponseDto; } -// // 리프레시 토큰으로 액세스토큰 재발급 -// @PostMapping("/token/refresh") -// public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { -// RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); -// Cookie[] list = request.getCookies(); -// -// if (list == null) { -// throw new DefaultException(ErrorCode.INVALID_CHECK); -// } -// -// Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> -// cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); -// -// if (refreshTokenCookie == null) { -// throw new DefaultException(ErrorCode.INVALID_CHECK); -// } -// -// String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); -// refreshTokenResponseDto.setAccessToken(accessToken); -// return refreshTokenResponseDto; -// } + // 리프레시 토큰으로 액세스토큰 재발급 + @PostMapping("/token/refresh") + public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { + RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); + Cookie[] list = request.getCookies(); + + if (list == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> + cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); + + if (refreshTokenCookie == null) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); + refreshTokenResponseDto.setAccessToken(accessToken); + return refreshTokenResponseDto; + } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 64bab2a8..c19b0b3a 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -34,18 +34,18 @@ public String getTokens(Long id, HttpServletResponse response) { return accessToken; } -// // 리프레시 토큰을 액세스 토큰으로 갱신 -// public String refreshToAccessToken(String refreshToken) { -// MemberDto memberDto = memberService.findByRefreshToken(refreshToken); -// -// if(memberDto == null) { -// throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); -// } -// -// if (!jwtTokenService.validateToken(refreshToken)) { -// throw new DefaultException(ErrorCode.INVALID_CHECK); -// } -// -// return jwtTokenService.createAccessToken(memberDto.getId().toString()); -// } + // 리프레시 토큰을 액세스 토큰으로 갱신 + public String refreshToAccessToken(String refreshToken) { + MemberDto memberDto = memberService.findByRefreshToken(refreshToken); + + if(memberDto == null) { + throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); + } + + if (!jwtTokenService.validateToken(refreshToken)) { + throw new DefaultException(ErrorCode.INVALID_CHECK); + } + + return jwtTokenService.createAccessToken(memberDto.getId().toString()); + } } diff --git a/src/main/java/com/ttubeog/global/config/SwaggerConfig.java b/src/main/java/com/ttubeog/global/config/SwaggerConfig.java index 9eea0a0b..303b7678 100644 --- a/src/main/java/com/ttubeog/global/config/SwaggerConfig.java +++ b/src/main/java/com/ttubeog/global/config/SwaggerConfig.java @@ -34,7 +34,9 @@ public OpenAPI openAPI() { return new OpenAPI() .info(info) .addSecurityItem(securityRequirement) - .components(components); + .components(components) + .addSecurityItem(new SecurityRequirement().addList(jwt)); + } } From 4ec6e4e84848addd2d481e7d8fd6d088ff96ad4f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 22 Jan 2024 03:10:23 +0900 Subject: [PATCH 064/356] =?UTF-8?q?[Refac]=20Exception=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 31 +++++++------------ .../NonExistentCommentException.java | 8 +++++ .../UnauthorizedMemberException.java | 8 +++++ 3 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java create mode 100644 src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 150d0a43..1773b996 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -8,14 +8,16 @@ import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; +import com.ttubeog.domain.comment.exception.NonExistentCommentException; +import com.ttubeog.domain.comment.exception.UnauthorizedMemberException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; -import org.apache.catalina.User; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,7 +26,6 @@ import java.util.List; import java.util.Optional; -import static java.lang.Math.abs; @RequiredArgsConstructor @Service @@ -38,9 +39,7 @@ public class CommentService { @Transactional public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentReq writeCommentReq) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - Member member = memberOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Comment comment = Comment.builder() .content(writeCommentReq.getContent()) @@ -71,19 +70,16 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentR @Transactional public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommentReq updateCommentReq) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional commentOptional = commentRepository.findById(updateCommentReq.getCommentId()); - DefaultAssert.isOptionalPresent(commentOptional); - Comment comment = commentOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Comment comment = commentRepository.findById(updateCommentReq.getCommentId()).orElseThrow(NonExistentCommentException::new); Member commentWriter = comment.getMember(); - if (commentWriter.getId() != memberOptional.get().getId()) { - DefaultAssert.isTrue(true, "해당 댓글의 작성자만 수정할 수 있습니다."); + if (commentWriter.getId() != member.getId()) { + throw new UnauthorizedMemberException(); } comment.updateContent(updateCommentReq.getContent()); + UpdateCommentRes updateCommentRes = UpdateCommentRes.builder() .commentId(comment.getId()) .content(comment.getContent()) @@ -101,13 +97,8 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommen @Transactional public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional commentOptional = commentRepository.findById(commentId); - DefaultAssert.isOptionalPresent(commentOptional); - Comment comment = commentOptional.get(); - + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Comment comment = commentRepository.findById(commentId).orElseThrow(NonExistentCommentException::new); commentRepository.delete(comment); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java b/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java new file mode 100644 index 00000000..07a54438 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.comment.exception; + +public class NonExistentCommentException extends RuntimeException { + + public NonExistentCommentException() { + super("존재하지 않는 댓글입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java b/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java new file mode 100644 index 00000000..1f4911df --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.comment.exception; + +public class UnauthorizedMemberException extends RuntimeException { + + public UnauthorizedMemberException() { + super("해당 댓글의 작성자가 아닙니다."); + } +} From 6f5f35378d270aea6c905907ad517b89bbac59a9 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 22 Jan 2024 17:35:01 +0900 Subject: [PATCH 065/356] =?UTF-8?q?[Remove]=20Auth=20Domain=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EB=B6=80=20=EC=82=AD=EC=A0=9C=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 2 + .../com/ttubeog/domain/auth/domain/Token.java | 36 ------------- .../CustomAuthorizationRequestRepository.java | 50 ------------------- .../domain/repository/TokenRepository.java | 13 ----- .../ttubeog/domain/auth/dto/KakaoInfoDto.java | 4 +- .../domain/auth/dto/OauthResponseDto.java | 2 + .../auth/service/KakaoOauthService.java | 2 +- 7 files changed, 7 insertions(+), 102 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/domain/Token.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index d97d376e..9d325b9b 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -11,6 +11,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; @@ -20,6 +21,7 @@ @RequiredArgsConstructor @Configuration +@EnableWebSecurity public class SecurityConfig { private final JwtTokenService jwtTokenService; private final MemberService memberService; diff --git a/src/main/java/com/ttubeog/domain/auth/domain/Token.java b/src/main/java/com/ttubeog/domain/auth/domain/Token.java deleted file mode 100644 index 2b175936..00000000 --- a/src/main/java/com/ttubeog/domain/auth/domain/Token.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ttubeog.domain.auth.domain; - -import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Table(name="token") -@Entity -public class Token extends BaseEntity { - - @Id - @Column(name = "user_email", length = 700 , nullable = false) - private String userEmail; - - @Column(name = "refresh_token", length = 1024 , nullable = false) - private String refreshToken; - - public Token(){} - - public Token updateRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - return this; - } - - @Builder - public Token(String userEmail, String refreshToken) { - this.userEmail = userEmail; - this.refreshToken = refreshToken; - } - -} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java deleted file mode 100644 index 09fa9c68..00000000 --- a/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ttubeog.domain.auth.domain.repository; - -import com.nimbusds.oauth2.sdk.util.StringUtils; -import com.ttubeog.global.config.security.util.CustomCookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; -import org.springframework.stereotype.Repository; - -@Repository -public class CustomAuthorizationRequestRepository implements AuthorizationRequestRepository{ - public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; - public static final String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; - - private static final int cookieExpireSeconds = 60*60; - - @Override - public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { - return CustomCookie.getCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) - .map(cookie -> CustomCookie.deserialize(cookie, OAuth2AuthorizationRequest.class)) - .orElse(null); - } - - @Override - public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) { - if (authorizationRequest == null) { - CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); - return; - } - - CustomCookie.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CustomCookie.serialize(authorizationRequest), cookieExpireSeconds); - String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); - if (StringUtils.isNotBlank(redirectUriAfterLogin)) { - CustomCookie.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSeconds); - } - } - - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { - return this.loadAuthorizationRequest(request); - } - - public void removeAuthorizationRequestCookies(HttpServletRequest request, HttpServletResponse response) { - CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); - } - -} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java deleted file mode 100644 index 09249d11..00000000 --- a/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ttubeog.domain.auth.domain.repository; - -import com.ttubeog.domain.auth.domain.Token; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface TokenRepository extends JpaRepository { - Optional findByUserEmail(String userEmail); - Optional findByRefreshToken(String refreshToken); -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java index e4eb653d..20933044 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java @@ -12,8 +12,8 @@ public class KakaoInfoDto { private String email; public KakaoInfoDto(Map info) { - this.id = Long.valueOf(info.get("id").toString()); + this.id = info.get("id") != null ? Long.valueOf(info.get("id").toString()) : null; this.email = info.get("email") != null - ? info.get(email).toString() : ""; + ? info.get("email").toString() : ""; } } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java index c5d3ddd8..f512778a 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java @@ -7,4 +7,6 @@ @Setter public class OauthResponseDto { private String accessToken; + private String refreshToken; + private boolean early; } diff --git a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java index 81f0ce14..9a28925a 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java @@ -39,7 +39,7 @@ public MemberDto getMemberProfileByToken(String accessToken) { .platform("kakao") .build(); - if(memberService.findById(memberDto.getId()) != null) { + if (memberService.findById(memberDto.getId()) != null) { memberService.update(memberDto); } else { memberService.save(memberDto); From dd8b82b5181f8f1879631db75903f2dfc2f13585 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 22 Jan 2024 18:35:45 +0900 Subject: [PATCH 066/356] =?UTF-8?q?[Feat]=20SecurityUtil=20=EC=9E=AC?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/OauthController.java | 7 ++-- .../ttubeog/domain/auth/filter/JwtFilter.java | 4 +- .../domain/auth/service/JwtTokenService.java | 6 +-- .../domain/auth/service/OauthService.java | 8 ++-- .../domain/auth/utils/SecurityUtil.java | 8 ++-- .../member/presentation/MemberController.java | 16 ++++++-- ...SimpleUrlAuthenticationFailureHandler.java | 38 ------------------- 7 files changed, 29 insertions(+), 58 deletions(-) delete mode 100644 src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index ad472190..b6ff81a4 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -3,9 +3,10 @@ import com.ttubeog.domain.auth.dto.OauthRequestDto; import com.ttubeog.domain.auth.dto.OauthResponseDto; import com.ttubeog.domain.auth.dto.RefreshTokenResponseDto; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.auth.service.OauthService; import com.ttubeog.global.error.DefaultException; -import com.ttubeog.global.payload.ErrorCode; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; @@ -46,14 +47,14 @@ public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { Cookie[] list = request.getCookies(); if (list == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); + throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); } Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); if (refreshTokenCookie == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); + throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); } String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index 52fce8ef..ae53a178 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -29,6 +29,7 @@ public class JwtFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); // Swagger UI 및 관련 리소스 경로에 대한 요청인 경우 토큰 검증 생략 if (isSwaggerPath(httpServletRequest.getRequestURI())) { @@ -42,8 +43,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo authenticateWithJwtToken(jwt); } } catch (CustomException ex) { - // JWT 검증 실패 시 예외 처리 - throw ex; + throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); } filterChain.doFilter(servletRequest, servletResponse); diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java index 944d569f..fed023df 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.global.error.DefaultException; -import com.ttubeog.global.payload.ErrorCode; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; @@ -83,7 +83,7 @@ public String getPayload(String token) { } catch (ExpiredJwtException e) { return e.getClaims().getSubject(); } catch (JwtException e) { - throw new DefaultException(ErrorCode.INVALID_AUTHENTICATION); + throw new CustomException(ErrorCode.UNAUTHORIZED); } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index c19b0b3a..6bb29196 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -1,9 +1,9 @@ package com.ttubeog.domain.auth.service; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.global.error.DefaultException; -import com.ttubeog.global.payload.ErrorCode; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -39,11 +39,11 @@ public String refreshToAccessToken(String refreshToken) { MemberDto memberDto = memberService.findByRefreshToken(refreshToken); if(memberDto == null) { - throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); + throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); } if (!jwtTokenService.validateToken(refreshToken)) { - throw new DefaultException(ErrorCode.INVALID_CHECK); + throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); } return jwtTokenService.createAccessToken(memberDto.getId().toString()); diff --git a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java index e37859ed..c50c7c40 100644 --- a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java +++ b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java @@ -1,8 +1,8 @@ package com.ttubeog.domain.auth.utils; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.global.config.security.token.UserPrincipal; -import com.ttubeog.global.error.DefaultException; -import com.ttubeog.global.payload.ErrorCode; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -13,7 +13,7 @@ public static long getCurrentMemeberId() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { - throw new DefaultException(ErrorCode.INVALID_CHECK); + throw new CustomException(ErrorCode.UNAUTHORIZED); } long memberId; @@ -21,7 +21,7 @@ public static long getCurrentMemeberId() { if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { memberId = userPrincipal.getId(); } else { - throw new DefaultException(ErrorCode.INVALID_PARAMETER); + throw new CustomException(ErrorCode.BAD_REQUEST); } return memberId; } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 7470281d..4428ac7a 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,6 +1,10 @@ package com.ttubeog.domain.member.presentation; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; +import com.ttubeog.domain.auth.utils.SecurityUtil; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -31,11 +35,15 @@ public class MemberController { @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @GetMapping - public ResponseEntity getCurrentMember( + @GetMapping("") + public MemberDto getCurrentMember( @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal ) { - return memberService.getCurrentUser(userPrincipal); - } + final long memberId = SecurityUtil.getCurrentMemeberId(); + MemberDto userDto = memberService.findById(memberId); + if(userDto == null) { + throw new CustomException(ErrorCode.NOT_EXIST_USER); + } + return userDto; } } diff --git a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java b/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java deleted file mode 100644 index a2099a52..00000000 --- a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ttubeog.global.config.security.handler; - -import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; -import com.ttubeog.global.config.security.util.CustomCookie; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - -import static com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository.REDIRECT_URI_PARAM_COOKIE_NAME; - -@RequiredArgsConstructor -@Component -public class CustomSimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler{ - private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; - - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - String targetUrl = CustomCookie.getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME) - .map(Cookie::getValue) - .orElse(("/")); - - targetUrl = UriComponentsBuilder.fromUriString(targetUrl) - .queryParam("error", exception.getLocalizedMessage()) - .build().toUriString(); - - customAuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response); - - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } -} From 593b1de1a6aa322457252aeddd167b46fffb9dc8 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Tue, 23 Jan 2024 02:11:02 +0900 Subject: [PATCH 067/356] =?UTF-8?q?[Feat]=20Spot.java=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20ERD=20=EB=A7=9E=EC=B6=B0=20=EA=B8=B0=EC=B4=88=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20Spot=20entity=20column=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/domain/Spot.java | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index a585790e..1b479be8 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -1,15 +1,65 @@ package com.ttubeog.domain.spot.domain; +import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.apache.ibatis.annotations.Many; +import org.hibernate.annotations.Fetch; +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter @Entity +@Table(name = "spot") public class Spot extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "info") + private String info; + + @Column(name = "latitude") + private Float latitude; + + @Column(name = "longitude") + private Float longitude; + + @Column(name = "image") + private String image; + + @Column(name = "starts") + private Float stars; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id)") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dong_area_id") + private DongArea dongArea; + + @Column(name = "detail_address") + private String detailAddress; + + public Spot(Long id, String name, String info, Float latitude, Float longitude, String image, Float stars, Member member, DongArea dongArea, String detailAddress) { + this.id = id; + this.name = name; + this.info = info; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.stars = stars; + this.member = member; + this.dongArea = dongArea; + this.detailAddress = detailAddress; + } } From 693598c4afc912c9ba61957f372af148e7c5f235 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 23 Jan 2024 03:36:22 +0900 Subject: [PATCH 068/356] =?UTF-8?q?[Feat]=20OpenFeign=EC=9D=84=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20Apple=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 10 +++++++++ .../java/com/ttubeog/TtubeogApplication.java | 1 + .../domain/auth/config/FeignClientConfig.java | 10 +++++++++ .../ttubeog/domain/auth/dto/TokenMapping.java | 21 ------------------- .../auth/dto/apple/AppleAuthRequest.java | 4 ++++ .../auth/dto/apple/AppleEventResponse.java | 4 ++++ .../domain/auth/dto/apple/ApplePublicKey.java | 11 ++++++++++ .../dto/apple/ApplePublicKeyResponse.java | 15 +++++++++++++ .../domain/auth/dto/apple/AppleUser.java | 4 ++++ .../ttubeog/domain/auth/dto/apple/Name.java | 4 ++++ .../auth/dto/{ => kakao}/KakaoInfoDto.java | 2 +- .../domain/auth/feign/AppleAuthClient.java | 12 +++++++++++ .../auth/service/KakaoOauthService.java | 2 +- 13 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java rename src/main/java/com/ttubeog/domain/auth/dto/{ => kakao}/KakaoInfoDto.java (91%) create mode 100644 src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java diff --git a/build.gradle b/build.gradle index 791d8988..bd597668 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,14 @@ repositories { maven { url 'https://jitpack.io' } } +dependencyManagement { + + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:2020.0.3" + } +} + + dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' @@ -42,6 +50,8 @@ dependencies { // discord log back implementation 'com.github.napstr:logback-discord-appender:1.0.0' + + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' } tasks.named('test') { diff --git a/src/main/java/com/ttubeog/TtubeogApplication.java b/src/main/java/com/ttubeog/TtubeogApplication.java index 414bf6f4..db61e68d 100644 --- a/src/main/java/com/ttubeog/TtubeogApplication.java +++ b/src/main/java/com/ttubeog/TtubeogApplication.java @@ -3,6 +3,7 @@ import com.ttubeog.global.config.YamlPropertySourceFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.EnableScheduling; diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java new file mode 100644 index 00000000..874c94d1 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java @@ -0,0 +1,10 @@ +package com.ttubeog.domain.auth.config; + +import com.ttubeog.TtubeogApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableFeignClients(basePackageClasses = TtubeogApplication.class) +public class FeignClientConfig { +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java b/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java deleted file mode 100644 index 01541579..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ttubeog.domain.auth.dto; - -import lombok.Builder; -import lombok.Data; - -@Data -public class TokenMapping { - private String userEmail; - private String accessToken; - private String refreshToken; - - public TokenMapping(){} - - @Builder - public TokenMapping(String userEmail, String accessToken, String refreshToken){ - this.userEmail = userEmail; - this.accessToken = accessToken; - this.refreshToken = refreshToken; - } - -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java new file mode 100644 index 00000000..fe168823 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.auth.dto.apple; + +public class AppleAuthRequest { +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java new file mode 100644 index 00000000..58a6fc3a --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.auth.dto.apple; + +public class AppleEventResponse { +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java new file mode 100644 index 00000000..edca2847 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java @@ -0,0 +1,11 @@ +package com.ttubeog.domain.auth.dto.apple; + +public record ApplePublicKey ( + String kty, + String kid, + String alg, + String n, + String e +) { + +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java new file mode 100644 index 00000000..3c8d7768 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.auth.dto.apple; + +import javax.naming.AuthenticationException; +import java.util.List; + +public record ApplePublicKeyResponse ( + List keys +) { + public ApplePublicKey getMatchedKey(String kid, String alg) throws AuthenticationException { + return keys.stream() + .filter(key -> key.kid().equals(kid) && key.alg().equals(alg)) + .findAny() + .orElseThrow(AuthenticationException::new); + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java new file mode 100644 index 00000000..61f4e9b6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.auth.dto.apple; + +public class AppleUser { +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java new file mode 100644 index 00000000..bddf2459 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.auth.dto.apple; + +public class Name { +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java similarity index 91% rename from src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java rename to src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java index 20933044..a05caecf 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.dto; +package com.ttubeog.domain.auth.dto.kakao; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java new file mode 100644 index 00000000..a4ab4402 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.auth.feign; + +import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient(name = "appleAuthClient", url = "https://appleid.apple.com/auth") +public interface AppleAuthClient { + @GetMapping + ApplePublicKey getAppleAuthPublicKey(); +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java index 9a28925a..18965dbe 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.dto.KakaoInfoDto; +import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; import lombok.RequiredArgsConstructor; From 4f0c5d8d7e71a50ce83092ae1de5c9cd2cc23998 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 23 Jan 2024 16:40:53 +0900 Subject: [PATCH 069/356] =?UTF-8?q?[Feat]=20Store=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/store/domain/Store.java | 48 +++++++++++++++++-- .../domain/store/domain/StoreType.java | 5 ++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/domain/StoreType.java diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 8dcbe437..dd80d139 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -1,15 +1,55 @@ package com.ttubeog.domain.store.domain; +import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.*; +import lombok.*; + +import java.util.List; @Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Table(name = "store") public class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "info") + private String info; + + @Column(name = "detailAddress") + private String detailAddress; + + @Column(name = "latitude") + private Float latitude; + + @Column(name = "longitude") + private Float longitude; + + @Column(name = "image") + private String image; + + @Column(name = "stars") + private Float stars; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private StoreType type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dong_area_id") + private DongArea dongArea; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; } diff --git a/src/main/java/com/ttubeog/domain/store/domain/StoreType.java b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java new file mode 100644 index 00000000..cb90e878 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java @@ -0,0 +1,5 @@ +package com.ttubeog.domain.store.domain; + +public enum StoreType { + restaurant, cafe +} From 20e8c805d07472ee225b05de9d6cdd066407690e Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 23 Jan 2024 18:30:18 +0900 Subject: [PATCH 070/356] =?UTF-8?q?[Feat]=20FeignClient=20Applie=20OAuth?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/FeignClientConfig.java | 6 +++++ .../domain/auth/dto/apple/ApplePublicKey.java | 24 ++++++++++++------- .../dto/apple/ApplePublicKeyResponse.java | 16 +++++++++---- .../domain/auth/feign/AppleAuthClient.java | 3 +-- .../domain/auth/service/AppleAuthService.java | 13 ++++++++++ .../domain/auth/utils/AppleJwtParser.java | 9 +++++++ 6 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java create mode 100644 src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java index 874c94d1..136129f6 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java @@ -1,10 +1,16 @@ package com.ttubeog.domain.auth.config; import com.ttubeog.TtubeogApplication; +import feign.Retryer; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableFeignClients(basePackageClasses = TtubeogApplication.class) public class FeignClientConfig { + @Bean + public Retryer retryer() { + return new Retryer.Default(1000, 1500, 1); + } } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java index edca2847..5525564f 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java @@ -1,11 +1,19 @@ package com.ttubeog.domain.auth.dto.apple; -public record ApplePublicKey ( - String kty, - String kid, - String alg, - String n, - String e -) { +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; -} +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +public class ApplePublicKey { + + private String kty; + private String kid; + private String use; + private String alg; + private String n; + private String e; +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java index 3c8d7768..68f345b8 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java @@ -1,14 +1,22 @@ package com.ttubeog.domain.auth.dto.apple; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + import javax.naming.AuthenticationException; import java.util.List; -public record ApplePublicKeyResponse ( - List keys -) { +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +public class ApplePublicKeyResponse { + private List keys; + public ApplePublicKey getMatchedKey(String kid, String alg) throws AuthenticationException { return keys.stream() - .filter(key -> key.kid().equals(kid) && key.alg().equals(alg)) + .filter(key -> key.getKid().equals(kid) && key.getAlg().equals(alg)) .findAny() .orElseThrow(AuthenticationException::new); } diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java index a4ab4402..243eca35 100644 --- a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java +++ b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java @@ -1,12 +1,11 @@ package com.ttubeog.domain.auth.feign; import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "appleAuthClient", url = "https://appleid.apple.com/auth") public interface AppleAuthClient { - @GetMapping + @GetMapping("/keys") ApplePublicKey getAppleAuthPublicKey(); } diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java new file mode 100644 index 00000000..400db9e2 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.feign.AppleAuthClient; +import com.ttubeog.domain.member.application.MemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AppleAuthService { + private final AppleAuthClient appleAuthClient; + private final MemberService memberService; +} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java new file mode 100644 index 00000000..c2e57cdc --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.auth.utils; + +import org.springframework.stereotype.Component; + +@Component +public class AppleJwtParser { + private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; + private static final int HEADER_INDEX = 0; +} From 54bd3765643907cd278b30905a2b0d63ec8c2065 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 23 Jan 2024 18:55:40 +0900 Subject: [PATCH 071/356] =?UTF-8?q?[Feat]=20Apple=20Login=20Public=20Key?= =?UTF-8?q?=20=EC=83=9D=EC=85=A9=20=EA=B5=AC=ED=98=84=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/exception/ErrorCode.java | 6 ++- .../domain/auth/service/JwtTokenService.java | 39 +++++++++++++++++++ .../domain/auth/utils/AppleJwtParser.java | 34 ++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java index 7fa0a68e..ba885686 100644 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java @@ -7,7 +7,11 @@ public enum ErrorCode { INVALID_ACCESS_TOKEN("유효하지 않은 액세스 토큰입니다.", HttpStatus.UNAUTHORIZED), INVALID_REFRESH_TOKEN("유효하지 않은 리프레시 토큰입니다.", HttpStatus.UNAUTHORIZED), BAD_REQUEST("잘못된 요청입니다.", HttpStatus.BAD_REQUEST), - NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED); + NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED), + INVALID_APPLE_OAUTH_TOKEN("Apple OAuth Identity Token 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), + PUBLIC_KEY_GENERATION_ERROR("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), + APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED); + private final String message; private final HttpStatus httpStatus; diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java index fed023df..c5a5750d 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -1,5 +1,7 @@ package com.ttubeog.domain.auth.service; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import io.jsonwebtoken.*; @@ -12,9 +14,18 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import javax.naming.AuthenticationException; +import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; +import java.util.Base64; import java.util.Date; +import java.util.Map; import java.util.Random; @Service @@ -25,6 +36,10 @@ public class JwtTokenService implements InitializingBean { private final long refreshTokenExpirationInSeconds; private static Key key; + private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; + private static final String KEY_ID_HEADER_KEY = "kid"; + private static final int POSITIVE_SIGN_NUMBER = 1; + public JwtTokenService( @Value("${jwt.secret-key}") String secretKey, @@ -121,4 +136,28 @@ public void addRefreshTokenToCookie(String refreshToken, HttpServletResponse res cookie.setHttpOnly(true); response.addCookie(cookie); } + + public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) throws AuthenticationException { + ApplePublicKey applePublicKey = + applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); + + return generatePublicKeyWithApplePublicKey(applePublicKey); + } + + public PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey applePublicKey) { + byte[] nBytes = Base64.getUrlDecoder().decode(applePublicKey.getN()); + byte[] eBytes = Base64.getUrlDecoder().decode(applePublicKey.getE()); + + BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); + BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); + + RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); + + try { + KeyFactory keyFactory = KeyFactory.getInstance(applePublicKey.getKty()); + return keyFactory.generatePublic(publicKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { + throw new CustomException(ErrorCode.PUBLIC_KEY_GENERATION_ERROR); + } + } } diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java index c2e57cdc..2f4c66e8 100644 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java +++ b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java @@ -1,9 +1,43 @@ package com.ttubeog.domain.auth.utils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.SignatureException; import org.springframework.stereotype.Component; +import java.security.PublicKey; +import java.util.Base64; +import java.util.Map; + @Component public class AppleJwtParser { private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; private static final int HEADER_INDEX = 0; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public Map parseHeaders(String identityToken) { + try { + String encodedHeader = identityToken.split(IDENTITY_TOKEN_VALUE_DELIMITER)[HEADER_INDEX]; + String decodeHeader = new String(Base64.getUrlDecoder().decode(encodedHeader)); + return OBJECT_MAPPER.readValue(decodeHeader, Map.class); + } catch (JsonProcessingException | ArrayIndexOutOfBoundsException e) { + throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); + } + } + + public Claims parsePublicKeyAndGetClaims(String idToken, PublicKey publicKey) { + try { + return Jwts.parser() + .setSigningKey(publicKey) + .parseClaimsJws(idToken) + .getBody(); + } catch (ExpiredJwtException e) { + throw new CustomException(ErrorCode.APPLE_OAUTH_TOKEN_EXPIRED); + } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { + throw new CustomException(ErrorCode.INVALID_APPLE_OAUTH_TOKEN); + } + } } From 6f6b67536177e294a2c94a136cbb6cb712580581 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 23 Jan 2024 19:08:27 +0900 Subject: [PATCH 072/356] =?UTF-8?q?[Feat]=20Apple=20Login=20Claims=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EA=B5=AC=ED=98=84=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/exception/ErrorCode.java | 3 +- .../auth/service/AppleClaimsValidator.java | 32 +++++++++++++ .../domain/auth/service/JwtTokenService.java | 39 --------------- .../auth/service/PublicKeyGenerator.java | 48 +++++++++++++++++++ .../domain/auth/utils/EncryptUtils.java | 27 +++++++++++ 5 files changed, 109 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java create mode 100644 src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java index ba885686..7547baa6 100644 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java @@ -10,7 +10,8 @@ public enum ErrorCode { NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED), INVALID_APPLE_OAUTH_TOKEN("Apple OAuth Identity Token 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), PUBLIC_KEY_GENERATION_ERROR("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), - APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED); + APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED), + APPLE_OAUTH_COMMUNICATION_ERROR("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR); private final String message; diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java new file mode 100644 index 00000000..33cf4055 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java @@ -0,0 +1,32 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.utils.EncryptUtils; +import io.jsonwebtoken.Claims; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class AppleClaimsValidator { + private static final String NONCE_KEY = "nonce"; + + private final String iss; + private final String clientId; + private final String nonce; + + + public AppleClaimsValidator( + @Value("${}") String iss, // 애플 api 요청 경로 + @Value("${}") String clientId, // apple developer에 생성된 Bundle ID 값 + @Value("${}") String nonce // csrf 공격 방지를 위한 임의의 문자열 + ) { + this.iss = iss; + this.clientId = clientId; + this.nonce = EncryptUtils.encrypt(nonce); + } + + public boolean isValid(Claims claims) { + return claims.getIssuer().contains(iss) && + claims.getAudience().equals(clientId) && + claims.get(NONCE_KEY, String.class).equals(nonce); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java index c5a5750d..fed023df 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -1,7 +1,5 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import io.jsonwebtoken.*; @@ -14,18 +12,9 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import javax.naming.AuthenticationException; -import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.Key; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPublicKeySpec; -import java.util.Base64; import java.util.Date; -import java.util.Map; import java.util.Random; @Service @@ -36,10 +25,6 @@ public class JwtTokenService implements InitializingBean { private final long refreshTokenExpirationInSeconds; private static Key key; - private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; - private static final String KEY_ID_HEADER_KEY = "kid"; - private static final int POSITIVE_SIGN_NUMBER = 1; - public JwtTokenService( @Value("${jwt.secret-key}") String secretKey, @@ -136,28 +121,4 @@ public void addRefreshTokenToCookie(String refreshToken, HttpServletResponse res cookie.setHttpOnly(true); response.addCookie(cookie); } - - public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) throws AuthenticationException { - ApplePublicKey applePublicKey = - applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); - - return generatePublicKeyWithApplePublicKey(applePublicKey); - } - - public PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey applePublicKey) { - byte[] nBytes = Base64.getUrlDecoder().decode(applePublicKey.getN()); - byte[] eBytes = Base64.getUrlDecoder().decode(applePublicKey.getE()); - - BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); - BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); - - RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); - - try { - KeyFactory keyFactory = KeyFactory.getInstance(applePublicKey.getKty()); - return keyFactory.generatePublic(publicKeySpec); - } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { - throw new CustomException(ErrorCode.PUBLIC_KEY_GENERATION_ERROR); - } - } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java new file mode 100644 index 00000000..a9c6e7ab --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java @@ -0,0 +1,48 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; + +import javax.naming.AuthenticationException; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; +import java.util.Base64; +import java.util.Map; + +public class PublicKeyGenerator { + + private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; + private static final String KEY_ID_HEADER_KEY = "kid"; + private static final int POSITIVE_SIGN_NUMBER = 1; + + + public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) throws AuthenticationException { + ApplePublicKey applePublicKey = + applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); + + return generatePublicKeyWithApplePublicKey(applePublicKey); + } + + public PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey applePublicKey) { + byte[] nBytes = Base64.getUrlDecoder().decode(applePublicKey.getN()); + byte[] eBytes = Base64.getUrlDecoder().decode(applePublicKey.getE()); + + BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); + BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); + + RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); + + try { + KeyFactory keyFactory = KeyFactory.getInstance(applePublicKey.getKty()); + return keyFactory.generatePublic(publicKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { + throw new CustomException(ErrorCode.PUBLIC_KEY_GENERATION_ERROR); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java b/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java new file mode 100644 index 00000000..2ae6ac11 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java @@ -0,0 +1,27 @@ +package com.ttubeog.domain.auth.utils; + +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class EncryptUtils { + private static final String ENCRYPT_ALGORITHM = "SHA-256"; + private static final String FORMAT_CODE = "%02x"; + + public static String encrypt(String value) { + try { + MessageDigest sha256 = MessageDigest.getInstance(ENCRYPT_ALGORITHM); + byte[] digest = sha256.digest(value.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(); + for (byte b : digest) { + hexString.append(String.format(FORMAT_CODE, b)); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new CustomException(ErrorCode.APPLE_OAUTH_COMMUNICATION_ERROR); + } + } +} From 2cbe8771fbf6e7d42700adc5d801db52cdc24ae0 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 23 Jan 2024 19:50:32 +0900 Subject: [PATCH 073/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EA=B3=84?= =?UTF-8?q?=EC=A0=95=20=EC=9C=A0=EC=A0=80=20=EC=A0=95=EB=B3=B4=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +- .../java/com/ttubeog/TtubeogApplication.java | 1 + .../domain/auth/config/FeignClientConfig.java | 6 --- .../controller/AppleOAtuhUserProvider.java | 43 +++++++++++++++++++ .../auth/controller/OauthController.java | 8 ++++ .../auth/dto/OAuthPlatformMemberResponse.java | 14 ++++++ .../auth/dto/apple/AppleLoginRequest.java | 13 ++++++ .../dto/apple/ApplePublicKeyResponse.java | 6 ++- .../domain/auth/exception/ErrorCode.java | 5 ++- .../domain/auth/feign/AppleAuthClient.java | 3 +- .../domain/auth/service/OauthService.java | 11 +++++ .../auth/service/PublicKeyGenerator.java | 4 +- 12 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java diff --git a/build.gradle b/build.gradle index bd597668..9da563da 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,8 @@ dependencies { // discord log back implementation 'com.github.napstr:logback-discord-appender:1.0.0' - implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' + implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.3") + implementation "org.springframework.cloud:spring-cloud-starter-openfeign" } tasks.named('test') { diff --git a/src/main/java/com/ttubeog/TtubeogApplication.java b/src/main/java/com/ttubeog/TtubeogApplication.java index db61e68d..f2ae0af0 100644 --- a/src/main/java/com/ttubeog/TtubeogApplication.java +++ b/src/main/java/com/ttubeog/TtubeogApplication.java @@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.EnableScheduling; diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java index 136129f6..874c94d1 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java @@ -1,16 +1,10 @@ package com.ttubeog.domain.auth.config; import com.ttubeog.TtubeogApplication; -import feign.Retryer; import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableFeignClients(basePackageClasses = TtubeogApplication.class) public class FeignClientConfig { - @Bean - public Retryer retryer() { - return new Retryer.Default(1000, 1500, 1); - } } diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java b/src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java new file mode 100644 index 00000000..afd1f6bf --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java @@ -0,0 +1,43 @@ +package com.ttubeog.domain.auth.controller; + +import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; +import com.ttubeog.domain.auth.feign.AppleAuthClient; +import com.ttubeog.domain.auth.service.AppleClaimsValidator; +import com.ttubeog.domain.auth.service.PublicKeyGenerator; +import com.ttubeog.domain.auth.utils.AppleJwtParser; +import io.jsonwebtoken.Claims; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.security.PublicKey; +import java.util.Map; + +@Component +@RequiredArgsConstructor +public class AppleOAtuhUserProvider { + private final AppleJwtParser appleJwtParser; + private final AppleAuthClient appleAuthClient; + private final PublicKeyGenerator publicKeyGenerator; + private final AppleClaimsValidator appleClaimsValidator; + + + public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) { + Map headers = appleJwtParser.parseHeaders(identityToken); + ApplePublicKeyResponse applePublicKeyResponse = appleAuthClient.getAppleAuthPublicKey(); + + PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeyResponse); + + Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); + validateClaims(claims); + return new OAuthPlatformMemberResponse(claims.getSubject(), claims.get("email", String.class)); + } + + private void validateClaims(Claims claims) { + if (!appleClaimsValidator.isValid(claims)) { + throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN_CLAIMS); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index b6ff81a4..0055f483 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.auth.dto.OauthRequestDto; import com.ttubeog.domain.auth.dto.OauthResponseDto; import com.ttubeog.domain.auth.dto.RefreshTokenResponseDto; +import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.auth.service.OauthService; @@ -40,6 +41,13 @@ public OauthResponseDto loginWithKaKao( return oauthResponseDto; } + // 애플 로그인 +// @PostMapping("/login/apple") +// public OauthResponseDto loginWithApple( +// @RequestBody AppleLoginRequest request) { +// OauthResponseDto responseDto = oauthService.loginWithApple() +// } + // 리프레시 토큰으로 액세스토큰 재발급 @PostMapping("/token/refresh") public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java new file mode 100644 index 00000000..52c2689c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.auth.dto; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class OAuthPlatformMemberResponse { + private String platformId; + private String email; +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java new file mode 100644 index 00000000..0b8363ec --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.auth.dto.apple; + +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@ToString +public class AppleLoginRequest { + @NotBlank(message = "1012: 공백일 수 없습니다.") + private String token; +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java index 68f345b8..51d3be94 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java @@ -1,5 +1,7 @@ package com.ttubeog.domain.auth.dto.apple; +import com.ttubeog.domain.auth.exception.CustomException; +import com.ttubeog.domain.auth.exception.ErrorCode; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -14,10 +16,10 @@ public class ApplePublicKeyResponse { private List keys; - public ApplePublicKey getMatchedKey(String kid, String alg) throws AuthenticationException { + public ApplePublicKey getMatchedKey(String kid, String alg) { return keys.stream() .filter(key -> key.getKid().equals(kid) && key.getAlg().equals(alg)) .findAny() - .orElseThrow(AuthenticationException::new); + .orElseThrow(() -> new CustomException(ErrorCode.INVALID_JWT_ALG_KID)); } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java index 7547baa6..995384b4 100644 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java @@ -11,7 +11,10 @@ public enum ErrorCode { INVALID_APPLE_OAUTH_TOKEN("Apple OAuth Identity Token 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), PUBLIC_KEY_GENERATION_ERROR("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED), - APPLE_OAUTH_COMMUNICATION_ERROR("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR); + APPLE_OAUTH_COMMUNICATION_ERROR("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), + INVALID_ACCESS_TOKEN_CLAIMS("Apple OAuth Claims 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), + INVALID_JWT_ALG_KID("Apple JWT 값의 alg, kid 정보가 올바르지 않습니다.", HttpStatus.BAD_REQUEST); + private final String message; diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java index 243eca35..e3774925 100644 --- a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java +++ b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java @@ -1,11 +1,12 @@ package com.ttubeog.domain.auth.feign; import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; +import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "appleAuthClient", url = "https://appleid.apple.com/auth") public interface AppleAuthClient { @GetMapping("/keys") - ApplePublicKey getAppleAuthPublicKey(); + ApplePublicKeyResponse getAppleAuthPublicKey(); } diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 6bb29196..8171e792 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -1,5 +1,8 @@ package com.ttubeog.domain.auth.service; +import com.ttubeog.domain.auth.controller.AppleOAtuhUserProvider; +import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; +import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.member.application.MemberService; @@ -14,6 +17,7 @@ public class OauthService { private final MemberService memberService; private final JwtTokenService jwtTokenService; private final KakaoOauthService kakaoOauthService; + private final AppleOAtuhUserProvider appleOAtuhUserProvider; // 카카오 로그인 public String loginWithKakao(String accessToken, HttpServletResponse response) { @@ -21,6 +25,13 @@ public String loginWithKakao(String accessToken, HttpServletResponse response) { return getTokens(memberDto.getId(), response); } +// // 애플 로그인 +// public String loginWithApple(AppleLoginRequest request, HttpServletResponse response) { +// OAuthPlatformMemberResponse applePlatformMember = +// appleOAtuhUserProvider.getApplePlatformMember(request.getToken()); +// return getTokens(applePlatformMember.getEmail(), response); +// } + // 액세스, 리프레시 토큰 생성 public String getTokens(Long id, HttpServletResponse response) { final String accessToken = jwtTokenService.createAccessToken(id.toString()); diff --git a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java index a9c6e7ab..b7f12e80 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java +++ b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; +import org.springframework.stereotype.Component; import javax.naming.AuthenticationException; import java.math.BigInteger; @@ -15,6 +16,7 @@ import java.util.Base64; import java.util.Map; +@Component public class PublicKeyGenerator { private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; @@ -22,7 +24,7 @@ public class PublicKeyGenerator { private static final int POSITIVE_SIGN_NUMBER = 1; - public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) throws AuthenticationException { + public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) { ApplePublicKey applePublicKey = applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); From d1d0fa46865d34950e40defad930325055462a1a Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 24 Jan 2024 12:40:11 +0900 Subject: [PATCH 074/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=84=9C=EB=B9=84=EC=8A=A4,=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/TtubeogApplication.java | 2 -- .../domain/auth/config/FeignClientConfig.java | 4 ++++ .../auth/controller/OauthController.java | 19 +++++++++++++------ .../auth/dto/apple/AppleLoginRequest.java | 2 +- .../domain/auth/service/AppleAuthService.java | 13 ------------- .../AppleOAtuhUserProvider.java | 10 ++++++---- .../domain/auth/service/OauthService.java | 16 ++++++++-------- .../AppleClaimsValidator.java | 8 ++++---- .../ttubeog/domain/member/dto/MemberDto.java | 3 +++ 9 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java rename src/main/java/com/ttubeog/domain/auth/{controller => service}/AppleOAtuhUserProvider.java (80%) rename src/main/java/com/ttubeog/domain/auth/{service => utils}/AppleClaimsValidator.java (71%) diff --git a/src/main/java/com/ttubeog/TtubeogApplication.java b/src/main/java/com/ttubeog/TtubeogApplication.java index f2ae0af0..414bf6f4 100644 --- a/src/main/java/com/ttubeog/TtubeogApplication.java +++ b/src/main/java/com/ttubeog/TtubeogApplication.java @@ -3,8 +3,6 @@ import com.ttubeog.global.config.YamlPropertySourceFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.EnableScheduling; diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java index 874c94d1..007a0faf 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java @@ -1,10 +1,14 @@ package com.ttubeog.domain.auth.config; import com.ttubeog.TtubeogApplication; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.cloud.commons.httpclient.HttpClientConfiguration; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignAutoConfiguration; import org.springframework.context.annotation.Configuration; @Configuration @EnableFeignClients(basePackageClasses = TtubeogApplication.class) +@ImportAutoConfiguration({FeignAutoConfiguration.class, HttpClientConfiguration.class}) public class FeignClientConfig { } diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 0055f483..0993f2f0 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -12,7 +12,9 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -41,12 +43,17 @@ public OauthResponseDto loginWithKaKao( return oauthResponseDto; } - // 애플 로그인 -// @PostMapping("/login/apple") -// public OauthResponseDto loginWithApple( -// @RequestBody AppleLoginRequest request) { -// OauthResponseDto responseDto = oauthService.loginWithApple() -// } + // 애플 로그인 + @PostMapping("/login/apple") + public OauthResponseDto loginWithApple( + @RequestBody @Valid AppleLoginRequest request, + HttpServletResponse response + ) { + OauthResponseDto oauthResponseDto = new OauthResponseDto(); + String accessToken = oauthService.loginWithApple(request.getAccessToken(), response); + oauthResponseDto.setAccessToken(accessToken); + return oauthResponseDto; + } // 리프레시 토큰으로 액세스토큰 재발급 @PostMapping("/token/refresh") diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java index 0b8363ec..cb5ac1fa 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java @@ -9,5 +9,5 @@ @ToString public class AppleLoginRequest { @NotBlank(message = "1012: 공백일 수 없습니다.") - private String token; + private String accessToken; } diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java deleted file mode 100644 index 400db9e2..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/AppleAuthService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.feign.AppleAuthClient; -import com.ttubeog.domain.member.application.MemberService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class AppleAuthService { - private final AppleAuthClient appleAuthClient; - private final MemberService memberService; -} diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java b/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java similarity index 80% rename from src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java rename to src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java index afd1f6bf..7acebb76 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/AppleOAtuhUserProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java @@ -1,13 +1,15 @@ -package com.ttubeog.domain.auth.controller; +package com.ttubeog.domain.auth.service; import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; +import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.auth.feign.AppleAuthClient; -import com.ttubeog.domain.auth.service.AppleClaimsValidator; +import com.ttubeog.domain.auth.utils.AppleClaimsValidator; import com.ttubeog.domain.auth.service.PublicKeyGenerator; import com.ttubeog.domain.auth.utils.AppleJwtParser; +import com.ttubeog.domain.member.dto.MemberDto; import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -24,7 +26,7 @@ public class AppleOAtuhUserProvider { private final AppleClaimsValidator appleClaimsValidator; - public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) { + public MemberDto getApplePlatformMember(String identityToken) { Map headers = appleJwtParser.parseHeaders(identityToken); ApplePublicKeyResponse applePublicKeyResponse = appleAuthClient.getAppleAuthPublicKey(); @@ -32,7 +34,7 @@ public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); validateClaims(claims); - return new OAuthPlatformMemberResponse(claims.getSubject(), claims.get("email", String.class)); + return new MemberDto(claims.getSubject(), claims.get("email", String.class)); } private void validateClaims(Claims claims) { diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 8171e792..86bfa36d 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -1,11 +1,10 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.controller.AppleOAtuhUserProvider; -import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; import com.ttubeog.domain.auth.exception.CustomException; import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.member.application.MemberService; +import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.MemberDto; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -15,6 +14,7 @@ @Service public class OauthService { private final MemberService memberService; + private final MemberRepository memberRepository; private final JwtTokenService jwtTokenService; private final KakaoOauthService kakaoOauthService; private final AppleOAtuhUserProvider appleOAtuhUserProvider; @@ -25,12 +25,11 @@ public String loginWithKakao(String accessToken, HttpServletResponse response) { return getTokens(memberDto.getId(), response); } -// // 애플 로그인 -// public String loginWithApple(AppleLoginRequest request, HttpServletResponse response) { -// OAuthPlatformMemberResponse applePlatformMember = -// appleOAtuhUserProvider.getApplePlatformMember(request.getToken()); -// return getTokens(applePlatformMember.getEmail(), response); -// } + // 애플 로그인 + public String loginWithApple(String accessToken, HttpServletResponse response) { + MemberDto memberDto = appleOAtuhUserProvider.getApplePlatformMember(accessToken); + return getTokens(memberDto.getId(), response); + } // 액세스, 리프레시 토큰 생성 public String getTokens(Long id, HttpServletResponse response) { @@ -59,4 +58,5 @@ public String refreshToAccessToken(String refreshToken) { return jwtTokenService.createAccessToken(memberDto.getId().toString()); } + } diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java similarity index 71% rename from src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java rename to src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java index 33cf4055..e66571af 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AppleClaimsValidator.java +++ b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.utils; import com.ttubeog.domain.auth.utils.EncryptUtils; import io.jsonwebtoken.Claims; @@ -15,9 +15,9 @@ public class AppleClaimsValidator { public AppleClaimsValidator( - @Value("${}") String iss, // 애플 api 요청 경로 - @Value("${}") String clientId, // apple developer에 생성된 Bundle ID 값 - @Value("${}") String nonce // csrf 공격 방지를 위한 임의의 문자열 + @Value("https://appleid.apple.com/") String iss, // 애플 api 요청 경로 + @Value("1234") String clientId, // apple developer에 생성된 Bundle ID 값 + @Value("1234") String nonce // csrf 공격 방지를 위한 임의의 문자열 ) { this.iss = iss; this.clientId = clientId; diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java index 4f160f8f..acd7a712 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -18,6 +18,9 @@ public class MemberDto { private String platform; private String refreshToken; + public MemberDto(String subject, String email) { + } + public static MemberDto toEntity(Member member) { return MemberDto.builder() .id(member.getId()) From a61872bd48c35266c66d0c8254880e5232bf7c64 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 15:04:12 +0900 Subject: [PATCH 075/356] =?UTF-8?q?[Feat]=20Game=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/game/domain/BasketballGame.java | 12 +++++++++++- .../java/com/ttubeog/domain/game/domain/Game.java | 13 +++++++++++++ .../com/ttubeog/domain/game/domain/GiftGame.java | 10 +++++++++- .../ttubeog/domain/game/domain/RouletteGame.java | 13 ++++++++----- .../ttubeog/domain/game/domain/RouletteOption.java | 10 +++++++++- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index b1e56474..6e886084 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.game.domain; +import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,7 +13,7 @@ @Getter @Entity @Table(name = "basketball_game") -public class BasketballGame { +public class BasketballGame extends BaseEntity { @Id @OneToOne @@ -24,4 +26,12 @@ public class BasketballGame { private Integer ballCount; private Integer successCount; + + @Builder + public BasketballGame(Game game, LocalDateTime timeLimit, Integer ballCount, Integer successCount) { + this.game = game; + this.timeLimit = timeLimit; + this.ballCount = ballCount; + this.successCount = successCount; + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index 7b82967f..bf4f1f92 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -1,8 +1,10 @@ package com.ttubeog.domain.game.domain; +import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -19,4 +21,15 @@ public abstract class Game extends BaseEntity { @Column(name = "type") @Enumerated(EnumType.STRING) private GameType type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "benefit_id") + private Benefit benefit; + + @Builder + public Game(Long id, GameType type, Benefit benefit) { + this.id = id; + this.type = type; + this.benefit = benefit; + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index d1f6b09f..9c2fcf9b 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.game.domain; +import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,7 +13,7 @@ @Getter @Entity @Table(name = "gift_game") -public class GiftGame { +public class GiftGame extends BaseEntity { @Id @OneToOne @@ -23,4 +25,10 @@ public class GiftGame { private Integer giftCount; + @Builder + public GiftGame(Game game, LocalDateTime timeLimit, Integer giftCount) { + this.game = game; + this.timeLimit = timeLimit; + this.giftCount = giftCount; + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index 48354d64..525da60d 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.game.domain; +import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,7 +13,7 @@ @Getter @Entity @Table(name = "roulette_game") -public class RouletteGame { +public class RouletteGame extends BaseEntity { @Id @OneToOne @@ -21,8 +23,9 @@ public class RouletteGame { private int optionCount; - // 연관 관계 매핑 - @OneToMany(mappedBy = "rouletteGame") - private List options; - + @Builder + public RouletteGame(Game game, int optionCount) { + this.game = game; + this.optionCount = optionCount; + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java index 481e6d20..098afa54 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.game.domain; +import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -9,7 +11,7 @@ @Getter @Entity @Table(name = "roulette_option") -public class RouletteOption { +public class RouletteOption extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -21,4 +23,10 @@ public class RouletteOption { private String content; + @Builder + public RouletteOption(Long optionId, RouletteGame rouletteGame, String content) { + this.optionId = optionId; + this.rouletteGame = rouletteGame; + this.content = content; + } } From 3a41a04f8193b7636af43e55b964e96f80a897f4 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 19:53:07 +0900 Subject: [PATCH 076/356] =?UTF-8?q?[Feat]=20GiftGame=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 중복 제거 확인 필요 --- .../presentation/BenefitController.java | 12 ++-- .../domain/game/application/GameService.java | 61 +++++++++++++++++++ .../com/ttubeog/domain/game/domain/Game.java | 15 ++++- .../ttubeog/domain/game/domain/GiftGame.java | 15 +++-- .../domain/repository/GiftGameRepository.java | 9 +++ .../game/dto/request/CreateGiftReq.java | 20 ++++++ .../game/dto/response/CreateGiftRes.java | 31 ++++++++++ .../game/presentation/GameController.java | 43 +++++++++++++ 8 files changed, 192 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/domain/repository/GiftGameRepository.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 84ca8ab8..3f0388f7 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -40,7 +40,7 @@ public class BenefitController { }) @PostMapping public ResponseEntity createBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody CreateBenefitReq createBenefitReq ) throws JsonProcessingException { @@ -55,7 +55,7 @@ public ResponseEntity createBenefit( }) @DeleteMapping("/{benefitId}") public ResponseEntity deleteBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -70,7 +70,7 @@ public ResponseEntity deleteBenefit( }) @PatchMapping public ResponseEntity updateBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody UpdateBenefitReq updateBenefitReq ) throws JsonProcessingException { @@ -85,7 +85,7 @@ public ResponseEntity updateBenefit( }) @PatchMapping("/{benefitId}") public ResponseEntity saveBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -100,7 +100,7 @@ public ResponseEntity saveBenefit( }) @PatchMapping("{benefitId}/use") public ResponseEntity useBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -115,7 +115,7 @@ public ResponseEntity useBenefit( }) @GetMapping public ResponseEntity findMyBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 1386396f..0903b560 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -1,6 +1,22 @@ package com.ttubeog.domain.game.application; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; +import com.ttubeog.domain.game.domain.Game; +import com.ttubeog.domain.game.domain.GameType; +import com.ttubeog.domain.game.domain.GiftGame; +import com.ttubeog.domain.game.domain.repository.GameRepository; +import com.ttubeog.domain.game.domain.repository.GiftGameRepository; +import com.ttubeog.domain.game.dto.request.CreateGiftReq; +import com.ttubeog.domain.game.dto.response.CreateGiftRes; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +24,49 @@ @Service @Transactional(readOnly = true) public class GameService { + + private final GameRepository gameRepository; + private final MemberRepository memberRepository; + private final BenefitRepository benefitRepository; + private final GiftGameRepository giftGameRepository; + + @Transactional + public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq createGiftReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(createGiftReq.getBenefitId() + ).orElseThrow(NonExistentBenefitException::new); + + //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 + + + Game game = Game.builder() + .benefit(benefit) + .type(GameType.gift) + .build(); + + gameRepository.save(game); + + GiftGame giftGame = GiftGame.builder() + .game(game) + .timeLimit(createGiftReq.getTimeLimit()) + .giftCount(createGiftReq.getGiftCount()) + .build(); + + giftGameRepository.save(giftGame); + + CreateGiftRes createGiftRes = CreateGiftRes.builder() + .gameId(game.getId()) + .benefitId(benefit.getId()) + .giftCount(giftGame.getGiftCount()) + .timeLimit(giftGame.getTimeLimit()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(createGiftRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index bf4f1f92..71b25b19 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -12,7 +12,7 @@ @Getter @Entity @Table(name = "game") -public abstract class Game extends BaseEntity { +public class Game extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -26,9 +26,18 @@ public abstract class Game extends BaseEntity { @JoinColumn(name = "benefit_id") private Benefit benefit; + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + private GiftGame giftGame; + + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + private BasketballGame basketballGame; + + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + private RouletteGame rouletteGame; + + @Builder - public Game(Long id, GameType type, Benefit benefit) { - this.id = id; + public Game(GameType type, Benefit benefit) { this.type = type; this.benefit = benefit; } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index 9c2fcf9b..a7c3cca6 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -7,7 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; +import java.time.LocalTime; @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @@ -16,17 +16,22 @@ public class GiftGame extends BaseEntity { @Id - @OneToOne - @MapsId + @Column(name = "game_id", nullable = false) + private Long id; + + @OneToOne(fetch = FetchType.EAGER) + @MapsId //@MapsId 는 @id로 지정한 컬럼에 @OneToOne 이나 @ManyToOne 관계를 매핑시키는 역할 @JoinColumn(name = "game_id") private Game game; - private LocalDateTime timeLimit; + @Column(name = "time_limit") + private LocalTime timeLimit; + @Column(name = "gift_count") private Integer giftCount; @Builder - public GiftGame(Game game, LocalDateTime timeLimit, Integer giftCount) { + public GiftGame(Game game, LocalTime timeLimit, Integer giftCount) { this.game = game; this.timeLimit = timeLimit; this.giftCount = giftCount; diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GiftGameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GiftGameRepository.java new file mode 100644 index 00000000..be950459 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GiftGameRepository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.game.domain.repository; + +import com.ttubeog.domain.game.domain.GiftGame; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface GiftGameRepository extends JpaRepository { +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java new file mode 100644 index 00000000..3aa2dd1d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java @@ -0,0 +1,20 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalTime; + +@Data +@Schema(description = "CreateGiftGameRequest") +public class CreateGiftReq { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "선물개수", example = "3") + private Integer giftCount; +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java new file mode 100644 index 00000000..23dadd1e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -0,0 +1,31 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalTime; + +@Data +public class CreateGiftRes { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "선물개수", example = "3") + private Integer giftCount; + + @Builder + public CreateGiftRes(Long benefitId, Long gameId, LocalTime timeLimit, Integer giftCount) { + this.benefitId = benefitId; + this.gameId = gameId; + this.timeLimit = timeLimit; + this.giftCount = giftCount; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index b339a292..7e658f94 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -1,7 +1,50 @@ package com.ttubeog.domain.game.presentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; +import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; +import com.ttubeog.domain.game.application.GameService; +import com.ttubeog.domain.game.dto.request.CreateGiftReq; +import com.ttubeog.domain.game.dto.response.CreateGiftRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ErrorResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "Game", description = "Game API") @RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/game") public class GameController { + + private final GameService gameService; + + //선물 게임 생성 + @Operation(summary = "선물 게임 생성", description = "선물 게임을 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "선물 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateGiftRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "선물 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PostMapping + public ResponseEntity createBenefit( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CreateGiftReq createGiftReq + ) throws JsonProcessingException { + return gameService.createGift(userPrincipal, createGiftReq); + } + } From 78dddb0e6f16fe7225e7a9afc141acd44524c43f Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 21:07:26 +0900 Subject: [PATCH 077/356] =?UTF-8?q?[Style]=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 도메인 Builder에 Id는 들어갈 필요가 없을 것 같아 수정했습니다. --- .../java/com/ttubeog/domain/benefit/domain/Benefit.java | 3 +-- .../com/ttubeog/domain/benefit/domain/MemberBenefit.java | 3 +-- .../domain/benefit/presentation/BenefitController.java | 8 -------- .../ttubeog/domain/game/presentation/GameController.java | 1 - 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index a81eae95..a702975f 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -27,8 +27,7 @@ public class Benefit extends BaseEntity { private Store store; @Builder - public Benefit(Long id, String content, BenefitType type, Store store) { - this.id = id; + public Benefit(String content, BenefitType type, Store store) { this.content = content; this.type = type; this.store = store; diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java index 17730f2b..7fb09e48 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java @@ -30,8 +30,7 @@ public class MemberBenefit extends BaseEntity { private Boolean expired = false; // 만료 여부 @Builder - public MemberBenefit(Long id, Member member, Benefit benefit, Boolean used, Boolean expired) { - this.id = id; + public MemberBenefit(Member member, Benefit benefit, Boolean used, Boolean expired) { this.member = member; this.benefit = benefit; this.used = used; diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 3f0388f7..d901a150 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -12,8 +12,6 @@ import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -40,7 +38,6 @@ public class BenefitController { }) @PostMapping public ResponseEntity createBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody CreateBenefitReq createBenefitReq ) throws JsonProcessingException { @@ -55,7 +52,6 @@ public ResponseEntity createBenefit( }) @DeleteMapping("/{benefitId}") public ResponseEntity deleteBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -70,7 +66,6 @@ public ResponseEntity deleteBenefit( }) @PatchMapping public ResponseEntity updateBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody UpdateBenefitReq updateBenefitReq ) throws JsonProcessingException { @@ -85,7 +80,6 @@ public ResponseEntity updateBenefit( }) @PatchMapping("/{benefitId}") public ResponseEntity saveBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -100,7 +94,6 @@ public ResponseEntity saveBenefit( }) @PatchMapping("{benefitId}/use") public ResponseEntity useBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -115,7 +108,6 @@ public ResponseEntity useBenefit( }) @GetMapping public ResponseEntity findMyBenefit( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 7e658f94..e172bf56 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -40,7 +40,6 @@ public class GameController { }) @PostMapping public ResponseEntity createBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody CreateGiftReq createGiftReq ) throws JsonProcessingException { From f0a05681de9d842dd47233c330668baea23dfd6d Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 25 Jan 2024 21:10:33 +0900 Subject: [PATCH 078/356] =?UTF-8?q?[Fix]=20:=20Swagger=20=EC=A0=95?= =?UTF-8?q?=EC=83=81=ED=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 ++++ .../com/ttubeog/domain/auth/config/SecurityConfig.java | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9b4ecbd6..dd004425 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,10 @@ out/ **/resources/database/ **/resources/oauth2/ **/resources/logback.xml +**/applicatioin.yml +**/application-database.yml +**/application-oauth2.yml +**/logback.yml Dockerfile docker-compose.yaml deploy_*.sh diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index d97d376e..cd87ffa1 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -53,6 +53,11 @@ public WebSecurityCustomizer webSecurityCustomizer(){ return web -> web.ignoring() .requestMatchers("/auth/login/**") - .requestMatchers("/swagger-ui/**", "/v2/api-docs", "/swagger-resources/**"); + .requestMatchers("/swagger-ui/**", + "/v2/api-docs", + "/swagger-resources/**", + "/h2-console/**", + "/favicon.ico", + "/v3/api-docs/**"); } } From c4cd44ec3386c81f88e9b2c7478f0862f0e44841 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 21:20:02 +0900 Subject: [PATCH 079/356] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=9E=84=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=ED=99=95=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 하나의 혜택에 중복되는 게임 저장 불가 --- .../com/ttubeog/domain/game/application/GameService.java | 5 ++++- .../domain/game/domain/repository/GameRepository.java | 3 +++ .../domain/game/exception/OverlappingGameException.java | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 0903b560..0d5d05f5 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -11,6 +11,7 @@ import com.ttubeog.domain.game.domain.repository.GiftGameRepository; import com.ttubeog.domain.game.dto.request.CreateGiftReq; import com.ttubeog.domain.game.dto.response.CreateGiftRes; +import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -38,7 +39,9 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - + if (gameRepository.existsByBenefit(benefit)) { + throw new OverlappingGameException(); + } Game game = Game.builder() .benefit(benefit) diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java index cda63ee9..290233dc 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java @@ -1,9 +1,12 @@ package com.ttubeog.domain.game.domain.repository; +import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.game.domain.Game; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface GameRepository extends JpaRepository { + + Boolean existsByBenefit(Benefit benefit); } diff --git a/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java b/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java new file mode 100644 index 00000000..ec10296b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.game.exception; + +public class OverlappingGameException extends RuntimeException { + + public OverlappingGameException() { + super("하나의 혜택에 같은 종류의 게임은 저장할 수 없습니다.");} +} From c6e4dc24f9616ba9b899f3b3c9e4bfa0f4e3bb4b Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 25 Jan 2024 21:43:03 +0900 Subject: [PATCH 080/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20requestBody=20=EC=88=98=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/auth/controller/OauthController.java | 2 +- .../ttubeog/domain/auth/dto/apple/AppleLoginRequest.java | 6 +++++- .../java/com/ttubeog/domain/auth/dto/apple/AppleUser.java | 8 ++++++++ src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java | 8 ++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 0993f2f0..66c24206 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -50,7 +50,7 @@ public OauthResponseDto loginWithApple( HttpServletResponse response ) { OauthResponseDto oauthResponseDto = new OauthResponseDto(); - String accessToken = oauthService.loginWithApple(request.getAccessToken(), response); + String accessToken = oauthService.loginWithApple(request.getIdentityToken(), response); oauthResponseDto.setAccessToken(accessToken); return oauthResponseDto; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java index cb5ac1fa..b49eba49 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java @@ -8,6 +8,10 @@ @Getter @ToString public class AppleLoginRequest { + private String state; + private String authorizationCode; @NotBlank(message = "1012: 공백일 수 없습니다.") - private String accessToken; + private String identityToken; + private AppleUser appleUser; + } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java index 61f4e9b6..7aecb7b5 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java @@ -1,4 +1,12 @@ package com.ttubeog.domain.auth.dto.apple; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@ToString public class AppleUser { + private String email; + private Name name; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java index bddf2459..7e8e0ba4 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java @@ -1,4 +1,12 @@ package com.ttubeog.domain.auth.dto.apple; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@ToString public class Name { + private String firstName; + private String lastName; } From 42ad7861a6cdff65c986704e6274d5edb9752c91 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 21:55:07 +0900 Subject: [PATCH 081/356] =?UTF-8?q?[Style]=20MemberBenefit=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EC=B2=B4=ED=81=AC=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/benefit/application/BenefitService.java | 4 +--- .../benefit/domain/repository/MemberBenefitRepository.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 69c9f6e0..141117e2 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -129,10 +129,8 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); - //유저에게 이미 있는 benefit인지 확인 - List memberBenefitList = memberBenefitRepository.findAllByBenefitAndCreatedAtIsAfter(benefit, LocalDateTime.now().minusMonths(1)); //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 - if (memberBenefitList.size() > 0) { + if (memberBenefitRepository.existsByBenefitAndCreatedAtIsAfter(benefit, LocalDateTime.now().minusMonths(1))) { throw new OverlappingBenefitException(); } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 9761a672..9494161c 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -15,7 +15,7 @@ @Repository public interface MemberBenefitRepository extends JpaRepository { - List findAllByBenefitAndCreatedAtIsAfter(Benefit benefit, LocalDateTime createdAt); + Boolean existsByBenefitAndCreatedAtIsAfter(Benefit benefit, LocalDateTime createdAt); Optional findByBenefitAndMemberAndExpiredIsFalse(Benefit benefit, Member member); From 2d315609a328305b4c3329cd43600609af50df13 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 22:12:36 +0900 Subject: [PATCH 082/356] =?UTF-8?q?[Style]=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/benefit/domain/MemberBenefit.java | 2 ++ .../com/ttubeog/domain/game/domain/BasketballGame.java | 8 +++++++- .../java/com/ttubeog/domain/game/domain/GiftGame.java | 2 +- .../java/com/ttubeog/domain/game/domain/RouletteGame.java | 7 +++++-- .../com/ttubeog/domain/game/domain/RouletteOption.java | 4 ++-- .../ttubeog/domain/game/presentation/GameController.java | 2 +- 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java index 7fb09e48..8584b997 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/MemberBenefit.java @@ -25,8 +25,10 @@ public class MemberBenefit extends BaseEntity { @JoinColumn(name = "benefit_id") private Benefit benefit; + @Column(name = "used") private Boolean used = false; // 사용 여부 + @Column(name = "expired") private Boolean expired = false; // 만료 여부 @Builder diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index 6e886084..af5cc116 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -16,15 +16,21 @@ public class BasketballGame extends BaseEntity { @Id - @OneToOne + @Column(name = "game_id", nullable = false) + private Long id; + + @OneToOne(fetch = FetchType.EAGER) @MapsId @JoinColumn(name = "game_id") private Game game; + @Column(name = "time_limit") private LocalDateTime timeLimit; + @Column(name = "ball_count") private Integer ballCount; + @Column(name = "success_count") private Integer successCount; @Builder diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index a7c3cca6..aeb7b804 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -20,7 +20,7 @@ public class GiftGame extends BaseEntity { private Long id; @OneToOne(fetch = FetchType.EAGER) - @MapsId //@MapsId 는 @id로 지정한 컬럼에 @OneToOne 이나 @ManyToOne 관계를 매핑시키는 역할 + @MapsId @JoinColumn(name = "game_id") private Game game; diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index 525da60d..11fcd768 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -14,13 +14,16 @@ @Entity @Table(name = "roulette_game") public class RouletteGame extends BaseEntity { - @Id - @OneToOne + @Column(name = "game_id", nullable = false) + private Long id; + + @OneToOne(fetch = FetchType.EAGER) @MapsId @JoinColumn(name = "game_id") private Game game; + @Column(name = "option_count") private int optionCount; @Builder diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java index 098afa54..6f352b12 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java @@ -21,11 +21,11 @@ public class RouletteOption extends BaseEntity { @JoinColumn(name = "roulette_game_id") private RouletteGame rouletteGame; + @Column(name = "content") private String content; @Builder - public RouletteOption(Long optionId, RouletteGame rouletteGame, String content) { - this.optionId = optionId; + public RouletteOption(RouletteGame rouletteGame, String content) { this.rouletteGame = rouletteGame; this.content = content; } diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index e172bf56..beac8593 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -39,7 +39,7 @@ public class GameController { @ApiResponse(responseCode = "400", description = "선물 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PostMapping - public ResponseEntity createBenefit( + public ResponseEntity createGift( @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody CreateGiftReq createGiftReq ) throws JsonProcessingException { From 0d3cf97f913604afab09be2094a4876881d0eecd Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 25 Jan 2024 22:31:45 +0900 Subject: [PATCH 083/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20requestBody=20identityToken=20=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/auth/dto/apple/AppleLoginRequest.java | 7 +++---- .../com/ttubeog/domain/auth/feign/AppleAuthClient.java | 2 +- .../ttubeog/domain/auth/utils/AppleClaimsValidator.java | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java index b49eba49..e8c7aa79 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java @@ -8,10 +8,9 @@ @Getter @ToString public class AppleLoginRequest { - private String state; - private String authorizationCode; +// private String state; +// private String authorizationCode; @NotBlank(message = "1012: 공백일 수 없습니다.") private String identityToken; - private AppleUser appleUser; - +// private AppleUser appleUser; } diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java index e3774925..d0062fdf 100644 --- a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java +++ b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java @@ -5,7 +5,7 @@ import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; -@FeignClient(name = "appleAuthClient", url = "https://appleid.apple.com/auth") +@FeignClient(name = "appleAuthClient", url = "${apple.auth.public-key-url}") public interface AppleAuthClient { @GetMapping("/keys") ApplePublicKeyResponse getAppleAuthPublicKey(); diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java index e66571af..7281abd5 100644 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java +++ b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java @@ -15,8 +15,8 @@ public class AppleClaimsValidator { public AppleClaimsValidator( - @Value("https://appleid.apple.com/") String iss, // 애플 api 요청 경로 - @Value("1234") String clientId, // apple developer에 생성된 Bundle ID 값 + @Value("${apple.iss}") String iss, // 애플 api 요청 경로 + @Value("${apple.bundle}") String clientId, // apple developer에 생성된 Bundle ID 값 @Value("1234") String nonce // csrf 공격 방지를 위한 임의의 문자열 ) { this.iss = iss; From ecbae8fd02912b90730a864099f12f491ab87b69 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Thu, 25 Jan 2024 23:02:38 +0900 Subject: [PATCH 084/356] =?UTF-8?q?[Feat]=20=EB=86=8D=EA=B5=AC=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=83=9D=EC=84=B1=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 53 ++++++++++++++++++- .../domain/game/domain/BasketballGame.java | 6 +-- .../repository/BasketBallRespository.java | 9 ++++ .../domain/repository/GameRepository.java | 3 +- .../game/dto/request/CreateBasketballReq.java | 23 ++++++++ .../dto/response/CreateBasketballRes.java | 35 ++++++++++++ .../game/dto/response/CreateGiftRes.java | 6 +-- .../game/presentation/GameController.java | 17 +++++- 8 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 0d5d05f5..75aa6aa2 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -4,12 +4,16 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; +import com.ttubeog.domain.game.domain.BasketballGame; import com.ttubeog.domain.game.domain.Game; import com.ttubeog.domain.game.domain.GameType; import com.ttubeog.domain.game.domain.GiftGame; +import com.ttubeog.domain.game.domain.repository.BasketBallRespository; import com.ttubeog.domain.game.domain.repository.GameRepository; import com.ttubeog.domain.game.domain.repository.GiftGameRepository; +import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; +import com.ttubeog.domain.game.dto.response.CreateBasketballRes; import com.ttubeog.domain.game.dto.response.CreateGiftRes; import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -30,7 +34,9 @@ public class GameService { private final MemberRepository memberRepository; private final BenefitRepository benefitRepository; private final GiftGameRepository giftGameRepository; + private final BasketBallRespository basketBallRespository; + // 선물게임 생성 @Transactional public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq createGiftReq) throws JsonProcessingException { @@ -39,7 +45,7 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefit(benefit)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.gift)) { throw new OverlappingGameException(); } @@ -72,4 +78,49 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c return ResponseEntity.ok(apiResponse); } + + // 농구게임 생성 + @Transactional + public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBasketballReq createBasketballReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(createBasketballReq.getBenefitId() + ).orElseThrow(NonExistentBenefitException::new); + + //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 + if (gameRepository.existsByBenefitAndType(benefit, GameType.basketball)) { + throw new OverlappingGameException(); + } + + Game game = Game.builder() + .benefit(benefit) + .type(GameType.basketball) + .build(); + + gameRepository.save(game); + + BasketballGame basketballGame = BasketballGame.builder() + .game(game) + .timeLimit(createBasketballReq.getTimeLimit()) + .ballCount(createBasketballReq.getBallCount()) + .successCount(createBasketballReq.getSuccessCount()) + .build(); + + basketBallRespository.save(basketballGame); + + CreateBasketballRes createBasketballRes = CreateBasketballRes.builder() + .gameId(game.getId()) + .benefitId(benefit.getId()) + .timeLimit(basketballGame.getTimeLimit()) + .ballCount(basketballGame.getBallCount()) + .successCount(basketballGame.getSuccessCount()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(createBasketballRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index af5cc116..6aee06a1 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -7,7 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; +import java.time.LocalTime; @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @@ -25,7 +25,7 @@ public class BasketballGame extends BaseEntity { private Game game; @Column(name = "time_limit") - private LocalDateTime timeLimit; + private LocalTime timeLimit; @Column(name = "ball_count") private Integer ballCount; @@ -34,7 +34,7 @@ public class BasketballGame extends BaseEntity { private Integer successCount; @Builder - public BasketballGame(Game game, LocalDateTime timeLimit, Integer ballCount, Integer successCount) { + public BasketballGame(Game game, LocalTime timeLimit, Integer ballCount, Integer successCount) { this.game = game; this.timeLimit = timeLimit; this.ballCount = ballCount; diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java new file mode 100644 index 00000000..f5a3fd5e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.game.domain.repository; + +import com.ttubeog.domain.game.domain.BasketballGame; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface BasketBallRespository extends JpaRepository { +} diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java index 290233dc..91e9bf73 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java @@ -2,11 +2,12 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.game.domain.Game; +import com.ttubeog.domain.game.domain.GameType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface GameRepository extends JpaRepository { - Boolean existsByBenefit(Benefit benefit); + Boolean existsByBenefitAndType(Benefit benefit, GameType type); } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java new file mode 100644 index 00000000..cb127e23 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java @@ -0,0 +1,23 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalTime; + +@Data +@Schema(description = "CreateBasketballGameRequest") +public class CreateBasketballReq { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "공 개수", example = "10") + private Integer ballCount; + + @Schema(description = "성공 개수", example = "4") + private Integer successCount; +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java new file mode 100644 index 00000000..0e9135bf --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java @@ -0,0 +1,35 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalTime; + +@Data +public class CreateBasketballRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "공 개수", example = "10") + private Integer ballCount; + + @Schema(description = "성공 개수", example = "4") + private Integer successCount; + + @Builder + public CreateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount) { + this.gameId = gameId; + this.benefitId = benefitId; + this.timeLimit = timeLimit; + this.ballCount = ballCount; + this.successCount = successCount; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java index 23dadd1e..5d266949 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -9,12 +9,12 @@ @Data public class CreateGiftRes { - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; - @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index beac8593..fe5875d4 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.game.application.GameService; +import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; import com.ttubeog.domain.game.dto.response.CreateGiftRes; import com.ttubeog.global.config.security.token.CurrentUser; @@ -38,7 +39,7 @@ public class GameController { @ApiResponse(responseCode = "200", description = "선물 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateGiftRes.class) ) } ), @ApiResponse(responseCode = "400", description = "선물 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @PostMapping + @PostMapping("/gift") public ResponseEntity createGift( @CurrentUser UserPrincipal userPrincipal, @Valid @RequestBody CreateGiftReq createGiftReq @@ -46,4 +47,18 @@ public ResponseEntity createGift( return gameService.createGift(userPrincipal, createGiftReq); } + //농구 게임 생성 + @Operation(summary = "농구 게임 생성", description = "농구 게임을 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "농구 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "농구 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PostMapping("/basketball") + public ResponseEntity createBasketball( + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CreateBasketballReq createBasketballReq + ) throws JsonProcessingException { + return gameService.createBasketBall(userPrincipal, createBasketballReq); + } + } From 2ad5702b64c8961e3bf3866bf2c15d5f63f937d6 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:11:34 +0900 Subject: [PATCH 085/356] =?UTF-8?q?[Feat]=20Store=20=EB=93=B1=EB=A1=9D=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 --- .../ttubeog/domain/area/domain/DongArea.java | 15 +++-- .../store/application/StoreService.java | 55 ++++++++++++++++++ .../store/dto/request/RegisterStoreReq.java | 34 +++++++++++ .../store/dto/response/RegisterStoreRes.java | 56 +++++++++++++++++++ .../store/presentation/StoreController.java | 38 ++++++++++++- 5 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java index b407a2cc..77f27a11 100644 --- a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java +++ b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java @@ -1,15 +1,22 @@ package com.ttubeog.domain.area.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "dong_area") public class DongArea extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + public DongArea(Long id) { + this.id = id; + } } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 7dec1608..0f9ffffb 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -1,6 +1,17 @@ package com.ttubeog.domain.store.application; +import com.ttubeog.domain.area.domain.DongArea; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +19,48 @@ @Service @Transactional(readOnly = true) public class StoreService { + + private final StoreRepository storeRepository; + private final MemberRepository memberRepository; + + // 매장 등록 + @Transactional + public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStoreReq registerStoreReq) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Store store = Store.builder() + .name(registerStoreReq.getName()) + .info(registerStoreReq.getInfo()) + .dongArea(new DongArea(registerStoreReq.getDongAreaId())) + .detailAddress(registerStoreReq.getDetailAddress()) + .latitude(registerStoreReq.getLatitude()) + .longitude(registerStoreReq.getLongitude()) + .image(registerStoreReq.getImage()) + .type(registerStoreReq.getType()) + .build(); + + storeRepository.save(store); + + RegisterStoreRes registerStoreRes = RegisterStoreRes.builder() + .storeId(store.getId()) + .memberId(member.getId()) + .name(store.getName()) + .info(store.getInfo()) + .dongAreaId(store.getDongArea().getId()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .type(store.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(registerStoreRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java new file mode 100644 index 00000000..e7f8ca18 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java @@ -0,0 +1,34 @@ +package com.ttubeog.domain.store.dto.request; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "매장 등록 Request") +public class RegisterStoreReq { + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; +} diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java new file mode 100644 index 00000000..622a8660 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -0,0 +1,56 @@ +package com.ttubeog.domain.store.dto.response; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +@Schema(description = "매장 등록 Response") +public class RegisterStoreRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "등록 유저 ID") + private Long memberId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; + + @Builder + public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, + String detailAddress,Float latitude, Float longitude, String image, StoreType type) { + this.storeId = storeId; + this.memberId = memberId; + this.name = name; + this.info = info; + this.dongAreaId = dongAreaId; + this.detailAddress = detailAddress; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.type = type; + } +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 01617b11..e9f554a5 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,7 +1,43 @@ package com.ttubeog.domain.store.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.ttubeog.domain.store.application.StoreService; +import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.ErrorResponse; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Store", description = "Store API") @RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/store") public class StoreController { + + private final StoreService storeService; + + // 매장 등록 + @Operation(summary = "매장 등록", description = "매장을 등록합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 등록 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = RegisterStoreRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 등록 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping + public ResponseEntity registerStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody RegisterStoreReq registerStoreReq + ) { + return storeService.registerStore(userPrincipal, registerStoreReq); + } + } From 71ba7956bab3ac932eeb7d6a16bc1c8b96d76f06 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:15:05 +0900 Subject: [PATCH 086/356] =?UTF-8?q?[Feat]=20Store=20=EC=88=98=EC=A0=95=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 --- .../store/application/StoreService.java | 42 +++++++++++++++++ .../ttubeog/domain/store/domain/Store.java | 28 +++++++++++ .../store/dto/request/UpdateStoreReq.java | 33 +++++++++++++ .../store/dto/response/UpdateStoreRes.java | 46 +++++++++++++++++++ .../exception/NonExistentStoreException.java | 8 ++++ .../exception/UnathorizedMemberException.java | 8 ++++ .../store/presentation/StoreController.java | 15 ++++++ 7 files changed, 180 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java create mode 100644 src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java create mode 100644 src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 0f9ffffb..a08049d2 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -6,7 +6,11 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.request.UpdateStoreReq; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.domain.store.dto.response.UpdateStoreRes; +import com.ttubeog.domain.store.exception.UnathorizedMemberException; +import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; @@ -63,4 +67,42 @@ public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStor return ResponseEntity.ok(apiResponse); } + // 매장 수정 + @Transactional + public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq updateStoreReq) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(updateStoreReq.getStoreId()).orElseThrow(NonExistentStoreException::new); + + Member storeOwner = store.getMember(); + if (storeOwner.getId() != member.getId()) { + throw new UnathorizedMemberException(); + } + + store.updateName(updateStoreReq.getName()); + store.updateInfo(updateStoreReq.getInfo()); + store.updateDetailAddress(updateStoreReq.getDetailAddress()); + store.updateLatitude(updateStoreReq.getLatitude()); + store.updateLongitude(updateStoreReq.getLongitude()); + store.updateImage(updateStoreReq.getImage()); + store.updateType(updateStoreReq.getType()); + + UpdateStoreRes updateStoreRes = UpdateStoreRes.builder() + .storeId(store.getId()) + .name(store.getName()) + .info(store.getInfo()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .type(store.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateStoreRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index dd80d139..e1c9b5a1 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -52,4 +52,32 @@ public class Store extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; + + public void updateName(String name) { + this.name = name; + } + + public void updateInfo(String info) { + this.info = info; + } + + public void updateDetailAddress(String detailAddress) { + this.detailAddress = detailAddress; + } + + public void updateLatitude(Float latitude) { + this.latitude = latitude; + } + + public void updateLongitude(Float longitude) { + this.longitude = longitude; + } + + public void updateImage(String image) { + this.image = image; + } + + public void updateType(StoreType type) { + this.type = type; + } } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java new file mode 100644 index 00000000..40e5bdba --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java @@ -0,0 +1,33 @@ +package com.ttubeog.domain.store.dto.request; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UpdateStoreReq { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "상세주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; +} diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java new file mode 100644 index 00000000..1b557760 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -0,0 +1,46 @@ +package com.ttubeog.domain.store.dto.response; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + +public class UpdateStoreRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "상세주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; + + @Builder + public UpdateStoreRes(Long storeId, String detailAddress, String name, String info, + Float latitude, Float longitude, String image, StoreType type) { + this.storeId = storeId; + this.detailAddress = detailAddress; + this.name = name; + this.info = info; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.type = type; + } +} + diff --git a/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java b/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java new file mode 100644 index 00000000..aafdf330 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class NonExistentStoreException extends RuntimeException { + + public NonExistentStoreException() { + super("존재하지 않는 매장입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java new file mode 100644 index 00000000..645d6234 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class UnathorizedMemberException extends RuntimeException { + + public UnathorizedMemberException() { + super("해당 매장에 대한 수정 권한이 없습니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index e9f554a5..8ad34726 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -2,7 +2,9 @@ import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.request.UpdateStoreReq; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; @@ -40,4 +42,17 @@ public ResponseEntity registerStore( return storeService.registerStore(userPrincipal, registerStoreReq); } + // 매장 수정 + @Operation(summary = "매장 수정", description = "매장 정보를 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateStoreRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PatchMapping + public ResponseEntity updateStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateStoreReq updateStoreReq + ) { + return storeService.updateStore(userPrincipal, updateStoreReq); + } } From 6707a9118d057354a3b9357553493e23427bda9d Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:41:48 +0900 Subject: [PATCH 087/356] =?UTF-8?q?[Feat]=20Store=20=EC=82=AD=EC=A0=9C=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 --- .../domain/store/application/StoreService.java | 17 +++++++++++++++++ .../store/presentation/StoreController.java | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index a08049d2..6ef58de3 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -14,6 +14,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -105,4 +106,20 @@ public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq return ResponseEntity.ok(apiResponse); } + + // 매장 삭제 + @Transactional + public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + storeRepository.delete(store); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 8ad34726..f856a1fc 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -55,4 +56,18 @@ public ResponseEntity updateStore( ) { return storeService.updateStore(userPrincipal, updateStoreReq); } + + // 매장 삭제 + @Operation(summary = "매장 삭제", description = "매장 정보를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "매장 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @DeleteMapping("/{storeId}") + public ResponseEntity deleteStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @PathVariable Long storeId + ) { + return storeService.deleteStore(userPrincipal, storeId); + } } From e0b5cfaf01efcac37b6a4e6e11499c31e897be63 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 25 Jan 2024 23:48:03 +0900 Subject: [PATCH 088/356] [Hotfix] add logback xml to git secret key --- .github/workflows/gradle.yml | 215 ++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 105 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f8b3a88b..c06e4346 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -29,59 +29,64 @@ jobs: runs-on: ubuntu-22.04 steps: - # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 - - name: Checkout branch - uses: actions/checkout@v3 - - # java 버전 세팅 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'zulu' - - # git ignore한 yml 파일들 github secret에서 복사해 오기 - - name: Copy secret - env: - OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} - OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} - OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} - - OCCUPY_SECRET_DIR: ./src/main/resources - OCCUPY_DB_SECRET_DIR: ./src/main/resources/database - OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 - - OCCUPY_SECRET_DIR_FILE_NAME: application.yml - OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml - OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml - run: | - mkdir $OCCUPY_DB_SECRET_DIR - mkdir $OCCUPY_OAUTH_SECRET_DIR - - touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - - echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - - # gradlew 실행 권한 부여 - - name: Run chmod to make gradlew executable - run: chmod +x ./gradlew - shell: bash - - # Build -> jar 파일 생성 - - name: Build with Gradle - run: ./gradlew clean build -x test - shell: bash - - - name: Upload Build artifacts - uses: actions/upload-artifact@v2 - with: - name: build-artifacts - path: | - build/libs/*.jar + # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 + - name: Checkout branch + uses: actions/checkout@v3 + + # java 버전 세팅 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'zulu' + + # git ignore한 yml 파일들 github secret에서 복사해 오기 + - name: Copy secret + env: + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} + OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} + OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} + OCCUPY_LOGBACK_SECRET: ${{ secrets.OCCUPY_LOGBACK_SECRET }} + + OCCUPY_SECRET_DIR: ./src/main/resources + OCCUPY_DB_SECRET_DIR: ./src/main/resources/database + OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 + OCCUPY_LOGBACK_SECRET_DIR: ./src/main/resources + + OCCUPY_SECRET_DIR_FILE_NAME: application.yml + OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml + OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml + OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback.xml + run: | + mkdir $OCCUPY_DB_SECRET_DIR + mkdir $OCCUPY_OAUTH_SECRET_DIR + + touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + touch $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + echo "$OCCUPY_LOGBACK_SECRET" > $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + # gradlew 실행 권한 부여 + - name: Run chmod to make gradlew executable + run: chmod +x ./gradlew + shell: bash + + # Build -> jar 파일 생성 + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + - name: Upload Build artifacts + uses: actions/upload-artifact@v2 + with: + name: build-artifacts + path: | + build/libs/*.jar deploy: @@ -90,55 +95,55 @@ jobs: runs-on: ubuntu-22.04 steps: -# # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) -# - name: Configure AWS credentials -# uses: aws-actions/configure-aws-credentials@v1 -# with: -# aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} -# aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} -# aws-region: ${{ env.AWS_REGION }} -# -# # (7) 빌드 결과물을 S3 버킷에 업로드 -# - name: Upload to AWS S3 -# run: | -# aws deploy push \ -# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ -# --ignore-hidden-files \ -# --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ -# --source . -# -# # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 -# - name: Deploy to AWS EC2 from S3 -# run: | -# aws deploy create-deployment \ -# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ -# --deployment-config-name CodeDeployDefault.AllAtOnce \ -# --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ -# --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip - - name: Download build artifacts - uses: actions/download-artifact@v2 - with: - name: build-artifacts - - # JAR 파일을 EC2에 배포하는 step - - name: SCP JAR to EC2 - uses: appleboy/scp-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - source: "*.jar" - target: "/home/ubuntu/app" - - # EC2에 SSH로 배포 커맨드를 입력하는 step - - name: Deploy SSH - uses: appleboy/ssh-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - # 기존 실행 중인 서버 종료 후 jar 파일 실행 - script: | - sudo fuser -k -n tcp 8080 - sleep 15 - sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file + # # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + # - name: Configure AWS credentials + # uses: aws-actions/configure-aws-credentials@v1 + # with: + # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + # aws-region: ${{ env.AWS_REGION }} + # + # # (7) 빌드 결과물을 S3 버킷에 업로드 + # - name: Upload to AWS S3 + # run: | + # aws deploy push \ + # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + # --ignore-hidden-files \ + # --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ + # --source . + # + # # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 + # - name: Deploy to AWS EC2 from S3 + # run: | + # aws deploy create-deployment \ + # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + # --deployment-config-name CodeDeployDefault.AllAtOnce \ + # --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + # --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip + - name: Download build artifacts + uses: actions/download-artifact@v2 + with: + name: build-artifacts + + # JAR 파일을 EC2에 배포하는 step + - name: SCP JAR to EC2 + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + source: "*.jar" + target: "/home/ubuntu/app" + + # EC2에 SSH로 배포 커맨드를 입력하는 step + - name: Deploy SSH + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo fuser -k -n tcp 8080 + sleep 15 + sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file From ed59ef1e0c574121ecf416ca5e702bf266c3290a Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:16:39 +0900 Subject: [PATCH 089/356] =?UTF-8?q?Revert=20"[Feat]=20=EC=95=A0=ED=94=8C?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20API=20=EA=B5=AC=ED=98=84"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 11 ---- .../domain/auth/config/FeignClientConfig.java | 14 ------ .../domain/auth/config/SecurityConfig.java | 2 - .../auth/controller/OauthController.java | 22 ++------ .../com/ttubeog/domain/auth/domain/Token.java | 36 +++++++++++++ .../CustomAuthorizationRequestRepository.java | 50 +++++++++++++++++++ .../domain/repository/TokenRepository.java | 13 +++++ .../auth/dto/{kakao => }/KakaoInfoDto.java | 6 +-- .../auth/dto/OAuthPlatformMemberResponse.java | 14 ------ .../domain/auth/dto/OauthResponseDto.java | 2 - .../ttubeog/domain/auth/dto/TokenMapping.java | 21 ++++++++ .../auth/dto/apple/AppleAuthRequest.java | 4 -- .../auth/dto/apple/AppleEventResponse.java | 4 -- .../auth/dto/apple/AppleLoginRequest.java | 16 ------ .../domain/auth/dto/apple/ApplePublicKey.java | 19 ------- .../dto/apple/ApplePublicKeyResponse.java | 25 ---------- .../domain/auth/dto/apple/AppleUser.java | 12 ----- .../ttubeog/domain/auth/dto/apple/Name.java | 12 ----- .../domain/auth/exception/ErrorCode.java | 10 +--- .../domain/auth/feign/AppleAuthClient.java | 12 ----- .../ttubeog/domain/auth/filter/JwtFilter.java | 4 +- .../auth/service/AppleOAtuhUserProvider.java | 45 ----------------- .../domain/auth/service/JwtTokenService.java | 6 +-- .../auth/service/KakaoOauthService.java | 4 +- .../domain/auth/service/OauthService.java | 19 ++----- .../auth/service/PublicKeyGenerator.java | 50 ------------------- .../auth/utils/AppleClaimsValidator.java | 32 ------------ .../domain/auth/utils/AppleJwtParser.java | 43 ---------------- .../domain/auth/utils/EncryptUtils.java | 27 ---------- .../domain/auth/utils/SecurityUtil.java | 8 +-- .../ttubeog/domain/member/dto/MemberDto.java | 3 -- .../member/presentation/MemberController.java | 16 ++---- ...SimpleUrlAuthenticationFailureHandler.java | 38 ++++++++++++++ 33 files changed, 184 insertions(+), 416 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/Token.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java rename src/main/java/com/ttubeog/domain/auth/dto/{kakao => }/KakaoInfoDto.java (60%) delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java create mode 100644 src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java diff --git a/build.gradle b/build.gradle index 9da563da..791d8988 100644 --- a/build.gradle +++ b/build.gradle @@ -15,14 +15,6 @@ repositories { maven { url 'https://jitpack.io' } } -dependencyManagement { - - imports { - mavenBom "org.springframework.cloud:spring-cloud-dependencies:2020.0.3" - } -} - - dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' @@ -50,9 +42,6 @@ dependencies { // discord log back implementation 'com.github.napstr:logback-discord-appender:1.0.0' - - implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.3") - implementation "org.springframework.cloud:spring-cloud-starter-openfeign" } tasks.named('test') { diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java deleted file mode 100644 index 007a0faf..00000000 --- a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ttubeog.domain.auth.config; - -import com.ttubeog.TtubeogApplication; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.cloud.commons.httpclient.HttpClientConfiguration; -import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableFeignClients(basePackageClasses = TtubeogApplication.class) -@ImportAutoConfiguration({FeignAutoConfiguration.class, HttpClientConfiguration.class}) -public class FeignClientConfig { -} diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index b7d9e893..cd87ffa1 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -11,7 +11,6 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; @@ -21,7 +20,6 @@ @RequiredArgsConstructor @Configuration -@EnableWebSecurity public class SecurityConfig { private final JwtTokenService jwtTokenService; private final MemberService memberService; diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java index 66c24206..ad472190 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java @@ -3,18 +3,14 @@ import com.ttubeog.domain.auth.dto.OauthRequestDto; import com.ttubeog.domain.auth.dto.OauthResponseDto; import com.ttubeog.domain.auth.dto.RefreshTokenResponseDto; -import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.auth.service.OauthService; import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,18 +39,6 @@ public OauthResponseDto loginWithKaKao( return oauthResponseDto; } - // 애플 로그인 - @PostMapping("/login/apple") - public OauthResponseDto loginWithApple( - @RequestBody @Valid AppleLoginRequest request, - HttpServletResponse response - ) { - OauthResponseDto oauthResponseDto = new OauthResponseDto(); - String accessToken = oauthService.loginWithApple(request.getIdentityToken(), response); - oauthResponseDto.setAccessToken(accessToken); - return oauthResponseDto; - } - // 리프레시 토큰으로 액세스토큰 재발급 @PostMapping("/token/refresh") public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { @@ -62,14 +46,14 @@ public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { Cookie[] list = request.getCookies(); if (list == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); + throw new DefaultException(ErrorCode.INVALID_CHECK); } Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); if (refreshTokenCookie == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); + throw new DefaultException(ErrorCode.INVALID_CHECK); } String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); diff --git a/src/main/java/com/ttubeog/domain/auth/domain/Token.java b/src/main/java/com/ttubeog/domain/auth/domain/Token.java new file mode 100644 index 00000000..2b175936 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/Token.java @@ -0,0 +1,36 @@ +package com.ttubeog.domain.auth.domain; + +import com.ttubeog.domain.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Table(name="token") +@Entity +public class Token extends BaseEntity { + + @Id + @Column(name = "user_email", length = 700 , nullable = false) + private String userEmail; + + @Column(name = "refresh_token", length = 1024 , nullable = false) + private String refreshToken; + + public Token(){} + + public Token updateRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + return this; + } + + @Builder + public Token(String userEmail, String refreshToken) { + this.userEmail = userEmail; + this.refreshToken = refreshToken; + } + +} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java new file mode 100644 index 00000000..09fa9c68 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java @@ -0,0 +1,50 @@ +package com.ttubeog.domain.auth.domain.repository; + +import com.nimbusds.oauth2.sdk.util.StringUtils; +import com.ttubeog.global.config.security.util.CustomCookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.stereotype.Repository; + +@Repository +public class CustomAuthorizationRequestRepository implements AuthorizationRequestRepository{ + public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; + public static final String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; + + private static final int cookieExpireSeconds = 60*60; + + @Override + public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { + return CustomCookie.getCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + .map(cookie -> CustomCookie.deserialize(cookie, OAuth2AuthorizationRequest.class)) + .orElse(null); + } + + @Override + public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) { + if (authorizationRequest == null) { + CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); + return; + } + + CustomCookie.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CustomCookie.serialize(authorizationRequest), cookieExpireSeconds); + String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); + if (StringUtils.isNotBlank(redirectUriAfterLogin)) { + CustomCookie.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSeconds); + } + } + + @Override + public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { + return this.loadAuthorizationRequest(request); + } + + public void removeAuthorizationRequestCookies(HttpServletRequest request, HttpServletResponse response) { + CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); + } + +} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java new file mode 100644 index 00000000..09249d11 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.auth.domain.repository; + +import com.ttubeog.domain.auth.domain.Token; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface TokenRepository extends JpaRepository { + Optional findByUserEmail(String userEmail); + Optional findByRefreshToken(String refreshToken); +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java similarity index 60% rename from src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java rename to src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java index a05caecf..e4eb653d 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.dto.kakao; +package com.ttubeog.domain.auth.dto; import lombok.AllArgsConstructor; import lombok.Getter; @@ -12,8 +12,8 @@ public class KakaoInfoDto { private String email; public KakaoInfoDto(Map info) { - this.id = info.get("id") != null ? Long.valueOf(info.get("id").toString()) : null; + this.id = Long.valueOf(info.get("id").toString()); this.email = info.get("email") != null - ? info.get("email").toString() : ""; + ? info.get(email).toString() : ""; } } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java deleted file mode 100644 index 52c2689c..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ttubeog.domain.auth.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class OAuthPlatformMemberResponse { - private String platformId; - private String email; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java index f512778a..c5d3ddd8 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java @@ -7,6 +7,4 @@ @Setter public class OauthResponseDto { private String accessToken; - private String refreshToken; - private boolean early; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java b/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java new file mode 100644 index 00000000..01541579 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/TokenMapping.java @@ -0,0 +1,21 @@ +package com.ttubeog.domain.auth.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +public class TokenMapping { + private String userEmail; + private String accessToken; + private String refreshToken; + + public TokenMapping(){} + + @Builder + public TokenMapping(String userEmail, String accessToken, String refreshToken){ + this.userEmail = userEmail; + this.accessToken = accessToken; + this.refreshToken = refreshToken; + } + +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java deleted file mode 100644 index fe168823..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -public class AppleAuthRequest { -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java deleted file mode 100644 index 58a6fc3a..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -public class AppleEventResponse { -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java deleted file mode 100644 index e8c7aa79..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import jakarta.validation.constraints.NotBlank; -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class AppleLoginRequest { -// private String state; -// private String authorizationCode; - @NotBlank(message = "1012: 공백일 수 없습니다.") - private String identityToken; -// private AppleUser appleUser; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java deleted file mode 100644 index 5525564f..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -public class ApplePublicKey { - - private String kty; - private String kid; - private String use; - private String alg; - private String n; - private String e; -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java deleted file mode 100644 index 51d3be94..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.naming.AuthenticationException; -import java.util.List; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -public class ApplePublicKeyResponse { - private List keys; - - public ApplePublicKey getMatchedKey(String kid, String alg) { - return keys.stream() - .filter(key -> key.getKid().equals(kid) && key.getAlg().equals(alg)) - .findAny() - .orElseThrow(() -> new CustomException(ErrorCode.INVALID_JWT_ALG_KID)); - } -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java deleted file mode 100644 index 7aecb7b5..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class AppleUser { - private String email; - private Name name; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java deleted file mode 100644 index 7e8e0ba4..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class Name { - private String firstName; - private String lastName; -} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java index 995384b4..7fa0a68e 100644 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java +++ b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java @@ -7,15 +7,7 @@ public enum ErrorCode { INVALID_ACCESS_TOKEN("유효하지 않은 액세스 토큰입니다.", HttpStatus.UNAUTHORIZED), INVALID_REFRESH_TOKEN("유효하지 않은 리프레시 토큰입니다.", HttpStatus.UNAUTHORIZED), BAD_REQUEST("잘못된 요청입니다.", HttpStatus.BAD_REQUEST), - NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED), - INVALID_APPLE_OAUTH_TOKEN("Apple OAuth Identity Token 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), - PUBLIC_KEY_GENERATION_ERROR("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), - APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED), - APPLE_OAUTH_COMMUNICATION_ERROR("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), - INVALID_ACCESS_TOKEN_CLAIMS("Apple OAuth Claims 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), - INVALID_JWT_ALG_KID("Apple JWT 값의 alg, kid 정보가 올바르지 않습니다.", HttpStatus.BAD_REQUEST); - - + NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED); private final String message; private final HttpStatus httpStatus; diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java deleted file mode 100644 index d0062fdf..00000000 --- a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.feign; - -import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; - -@FeignClient(name = "appleAuthClient", url = "${apple.auth.public-key-url}") -public interface AppleAuthClient { - @GetMapping("/keys") - ApplePublicKeyResponse getAppleAuthPublicKey(); -} diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java index ae53a178..52fce8ef 100644 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java @@ -29,7 +29,6 @@ public class JwtFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; - logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); // Swagger UI 및 관련 리소스 경로에 대한 요청인 경우 토큰 검증 생략 if (isSwaggerPath(httpServletRequest.getRequestURI())) { @@ -43,7 +42,8 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo authenticateWithJwtToken(jwt); } } catch (CustomException ex) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); + // JWT 검증 실패 시 예외 처리 + throw ex; } filterChain.doFilter(servletRequest, servletResponse); diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java b/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java deleted file mode 100644 index 7acebb76..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.feign.AppleAuthClient; -import com.ttubeog.domain.auth.utils.AppleClaimsValidator; -import com.ttubeog.domain.auth.service.PublicKeyGenerator; -import com.ttubeog.domain.auth.utils.AppleJwtParser; -import com.ttubeog.domain.member.dto.MemberDto; -import io.jsonwebtoken.Claims; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.security.PublicKey; -import java.util.Map; - -@Component -@RequiredArgsConstructor -public class AppleOAtuhUserProvider { - private final AppleJwtParser appleJwtParser; - private final AppleAuthClient appleAuthClient; - private final PublicKeyGenerator publicKeyGenerator; - private final AppleClaimsValidator appleClaimsValidator; - - - public MemberDto getApplePlatformMember(String identityToken) { - Map headers = appleJwtParser.parseHeaders(identityToken); - ApplePublicKeyResponse applePublicKeyResponse = appleAuthClient.getAppleAuthPublicKey(); - - PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeyResponse); - - Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); - validateClaims(claims); - return new MemberDto(claims.getSubject(), claims.get("email", String.class)); - } - - private void validateClaims(Claims claims) { - if (!appleClaimsValidator.isValid(claims)) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN_CLAIMS); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java index fed023df..944d569f 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; @@ -83,7 +83,7 @@ public String getPayload(String token) { } catch (ExpiredJwtException e) { return e.getClaims().getSubject(); } catch (JwtException e) { - throw new CustomException(ErrorCode.UNAUTHORIZED); + throw new DefaultException(ErrorCode.INVALID_AUTHENTICATION); } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java index 18965dbe..81f0ce14 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; +import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; import lombok.RequiredArgsConstructor; @@ -39,7 +39,7 @@ public MemberDto getMemberProfileByToken(String accessToken) { .platform("kakao") .build(); - if (memberService.findById(memberDto.getId()) != null) { + if(memberService.findById(memberDto.getId()) != null) { memberService.update(memberDto); } else { memberService.save(memberDto); diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java index 86bfa36d..c19b0b3a 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java @@ -1,11 +1,9 @@ package com.ttubeog.domain.auth.service; -import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,10 +12,8 @@ @Service public class OauthService { private final MemberService memberService; - private final MemberRepository memberRepository; private final JwtTokenService jwtTokenService; private final KakaoOauthService kakaoOauthService; - private final AppleOAtuhUserProvider appleOAtuhUserProvider; // 카카오 로그인 public String loginWithKakao(String accessToken, HttpServletResponse response) { @@ -25,12 +21,6 @@ public String loginWithKakao(String accessToken, HttpServletResponse response) { return getTokens(memberDto.getId(), response); } - // 애플 로그인 - public String loginWithApple(String accessToken, HttpServletResponse response) { - MemberDto memberDto = appleOAtuhUserProvider.getApplePlatformMember(accessToken); - return getTokens(memberDto.getId(), response); - } - // 액세스, 리프레시 토큰 생성 public String getTokens(Long id, HttpServletResponse response) { final String accessToken = jwtTokenService.createAccessToken(id.toString()); @@ -49,14 +39,13 @@ public String refreshToAccessToken(String refreshToken) { MemberDto memberDto = memberService.findByRefreshToken(refreshToken); if(memberDto == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); + throw new DefaultException(ErrorCode.INVALID_OPTIONAL_ISPRESENT); } if (!jwtTokenService.validateToken(refreshToken)) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); + throw new DefaultException(ErrorCode.INVALID_CHECK); } return jwtTokenService.createAccessToken(memberDto.getId().toString()); } - } diff --git a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java deleted file mode 100644 index b7f12e80..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import org.springframework.stereotype.Component; - -import javax.naming.AuthenticationException; -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPublicKeySpec; -import java.util.Base64; -import java.util.Map; - -@Component -public class PublicKeyGenerator { - - private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; - private static final String KEY_ID_HEADER_KEY = "kid"; - private static final int POSITIVE_SIGN_NUMBER = 1; - - - public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) { - ApplePublicKey applePublicKey = - applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); - - return generatePublicKeyWithApplePublicKey(applePublicKey); - } - - public PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey applePublicKey) { - byte[] nBytes = Base64.getUrlDecoder().decode(applePublicKey.getN()); - byte[] eBytes = Base64.getUrlDecoder().decode(applePublicKey.getE()); - - BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); - BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); - - RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); - - try { - KeyFactory keyFactory = KeyFactory.getInstance(applePublicKey.getKty()); - return keyFactory.generatePublic(publicKeySpec); - } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { - throw new CustomException(ErrorCode.PUBLIC_KEY_GENERATION_ERROR); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java deleted file mode 100644 index 7281abd5..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.ttubeog.domain.auth.utils.EncryptUtils; -import io.jsonwebtoken.Claims; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -public class AppleClaimsValidator { - private static final String NONCE_KEY = "nonce"; - - private final String iss; - private final String clientId; - private final String nonce; - - - public AppleClaimsValidator( - @Value("${apple.iss}") String iss, // 애플 api 요청 경로 - @Value("${apple.bundle}") String clientId, // apple developer에 생성된 Bundle ID 값 - @Value("1234") String nonce // csrf 공격 방지를 위한 임의의 문자열 - ) { - this.iss = iss; - this.clientId = clientId; - this.nonce = EncryptUtils.encrypt(nonce); - } - - public boolean isValid(Claims claims) { - return claims.getIssuer().contains(iss) && - claims.getAudience().equals(clientId) && - claims.get(NONCE_KEY, String.class).equals(nonce); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java deleted file mode 100644 index 2f4c66e8..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.SignatureException; -import org.springframework.stereotype.Component; - -import java.security.PublicKey; -import java.util.Base64; -import java.util.Map; - -@Component -public class AppleJwtParser { - private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; - private static final int HEADER_INDEX = 0; - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - public Map parseHeaders(String identityToken) { - try { - String encodedHeader = identityToken.split(IDENTITY_TOKEN_VALUE_DELIMITER)[HEADER_INDEX]; - String decodeHeader = new String(Base64.getUrlDecoder().decode(encodedHeader)); - return OBJECT_MAPPER.readValue(decodeHeader, Map.class); - } catch (JsonProcessingException | ArrayIndexOutOfBoundsException e) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); - } - } - - public Claims parsePublicKeyAndGetClaims(String idToken, PublicKey publicKey) { - try { - return Jwts.parser() - .setSigningKey(publicKey) - .parseClaimsJws(idToken) - .getBody(); - } catch (ExpiredJwtException e) { - throw new CustomException(ErrorCode.APPLE_OAUTH_TOKEN_EXPIRED); - } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { - throw new CustomException(ErrorCode.INVALID_APPLE_OAUTH_TOKEN); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java b/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java deleted file mode 100644 index 2ae6ac11..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class EncryptUtils { - private static final String ENCRYPT_ALGORITHM = "SHA-256"; - private static final String FORMAT_CODE = "%02x"; - - public static String encrypt(String value) { - try { - MessageDigest sha256 = MessageDigest.getInstance(ENCRYPT_ALGORITHM); - byte[] digest = sha256.digest(value.getBytes(StandardCharsets.UTF_8)); - StringBuilder hexString = new StringBuilder(); - for (byte b : digest) { - hexString.append(String.format(FORMAT_CODE, b)); - } - return hexString.toString(); - } catch (NoSuchAlgorithmException e) { - throw new CustomException(ErrorCode.APPLE_OAUTH_COMMUNICATION_ERROR); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java index c50c7c40..e37859ed 100644 --- a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java +++ b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java @@ -1,8 +1,8 @@ package com.ttubeog.domain.auth.utils; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -13,7 +13,7 @@ public static long getCurrentMemeberId() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { - throw new CustomException(ErrorCode.UNAUTHORIZED); + throw new DefaultException(ErrorCode.INVALID_CHECK); } long memberId; @@ -21,7 +21,7 @@ public static long getCurrentMemeberId() { if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { memberId = userPrincipal.getId(); } else { - throw new CustomException(ErrorCode.BAD_REQUEST); + throw new DefaultException(ErrorCode.INVALID_PARAMETER); } return memberId; } diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java index acd7a712..4f160f8f 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -18,9 +18,6 @@ public class MemberDto { private String platform; private String refreshToken; - public MemberDto(String subject, String email) { - } - public static MemberDto toEntity(Member member) { return MemberDto.builder() .id(member.getId()) diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 4428ac7a..7470281d 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,10 +1,6 @@ package com.ttubeog.domain.member.presentation; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.utils.SecurityUtil; import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -35,15 +31,11 @@ public class MemberController { @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @GetMapping("") - public MemberDto getCurrentMember( + @GetMapping + public ResponseEntity getCurrentMember( @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal ) { - final long memberId = SecurityUtil.getCurrentMemeberId(); - MemberDto userDto = memberService.findById(memberId); - if(userDto == null) { - throw new CustomException(ErrorCode.NOT_EXIST_USER); - } - return userDto; } + return memberService.getCurrentUser(userPrincipal); + } } diff --git a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java b/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java new file mode 100644 index 00000000..a2099a52 --- /dev/null +++ b/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java @@ -0,0 +1,38 @@ +package com.ttubeog.global.config.security.handler; + +import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; +import com.ttubeog.global.config.security.util.CustomCookie; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; + +import static com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository.REDIRECT_URI_PARAM_COOKIE_NAME; + +@RequiredArgsConstructor +@Component +public class CustomSimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler{ + private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + String targetUrl = CustomCookie.getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME) + .map(Cookie::getValue) + .orElse(("/")); + + targetUrl = UriComponentsBuilder.fromUriString(targetUrl) + .queryParam("error", exception.getLocalizedMessage()) + .build().toUriString(); + + customAuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response); + + getRedirectStrategy().sendRedirect(request, response, targetUrl); + } +} From 8e37d8b01ea54a068054d5b5168ff5ea9ad8fa5e Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:28:10 +0900 Subject: [PATCH 090/356] Update gradle.yml --- .github/workflows/gradle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c06e4346..11f5fe6e 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -56,7 +56,7 @@ jobs: OCCUPY_SECRET_DIR_FILE_NAME: application.yml OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml - OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback.xml + OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback-test.xml run: | mkdir $OCCUPY_DB_SECRET_DIR mkdir $OCCUPY_OAUTH_SECRET_DIR @@ -146,4 +146,4 @@ jobs: script: | sudo fuser -k -n tcp 8080 sleep 15 - sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file + sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & From fcec0306948fe55a28f71e2242ef344ee50aefaf Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:09:38 +0900 Subject: [PATCH 091/356] Update gradle.yml --- .github/workflows/gradle.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 11f5fe6e..e4b98eba 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -94,24 +94,24 @@ jobs: needs: build runs-on: ubuntu-22.04 - steps: - # # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) - # - name: Configure AWS credentials - # uses: aws-actions/configure-aws-credentials@v1 - # with: - # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - # aws-region: ${{ env.AWS_REGION }} - # - # # (7) 빌드 결과물을 S3 버킷에 업로드 - # - name: Upload to AWS S3 - # run: | - # aws deploy push \ - # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - # --ignore-hidden-files \ - # --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ - # --source . - # + steps: + # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + # (7) 빌드 결과물을 S3 버킷에 업로드 + - name: Upload to AWS S3 + run: | + aws deploy push \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --ignore-hidden-files \ + --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ + --source . + # # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 # - name: Deploy to AWS EC2 from S3 # run: | From 3b60cc1864c471139f60976a995d2e32f159eb27 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 26 Jan 2024 01:19:15 +0900 Subject: [PATCH 092/356] =?UTF-8?q?[Feat]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../domain/auth/config/SecurityConfig.java | 9 +- .../auth/controller/AuthController.java | 29 ++++ .../auth/controller/OauthController.java | 79 ----------- .../ttubeog/domain/auth/domain/Platform.java | 29 ++++ .../ttubeog/domain/auth/domain/Status.java | 26 ++++ .../domain/auth/dto/OauthRequestDto.java | 8 -- .../domain/auth/dto/OauthResponseDto.java | 12 -- .../auth/dto/RefreshTokenResponseDto.java | 11 -- .../auth/dto/apple/AppleAuthRequest.java | 4 - .../auth/dto/apple/AppleEventResponse.java | 4 - .../auth/dto/apple/AppleLoginRequest.java | 16 --- .../domain/auth/dto/apple/ApplePublicKey.java | 19 --- .../dto/apple/ApplePublicKeyResponse.java | 25 ---- .../domain/auth/dto/apple/AppleUser.java | 12 -- .../ttubeog/domain/auth/dto/apple/Name.java | 12 -- .../domain/auth/dto/kakao/KakaoInfoDto.java | 19 --- .../KakaoLoginRequest.java} | 12 +- .../auth/dto/response/OAuthTokenResponse.java | 12 ++ .../AccessTokenExpiredException.java | 6 + .../auth/exception/CustomException.java | 16 --- .../domain/auth/exception/ErrorCode.java | 35 ----- .../domain/auth/exception/ErrorResponse.java | 16 --- .../exception/ExceptionHandlerFilter.java | 38 ------ .../exception/GlobalExceptionHandler.java | 40 ------ .../InvalidAccessTokenException.java | 6 + .../exception/InvalidStatusException.java | 7 + .../exception/NotFoundMemberException.java | 9 ++ .../auth/exception/PlatformException.java | 8 ++ .../domain/auth/feign/AppleAuthClient.java | 12 -- .../ttubeog/domain/auth/filter/JwtFilter.java | 78 ----------- .../auth/service/AppleOAtuhUserProvider.java | 45 ------- .../domain/auth/service/AuthService.java | 59 +++++++++ .../domain/auth/service/JwtTokenProvider.java | 65 +++++++++ .../domain/auth/service/JwtTokenService.java | 124 ------------------ .../auth/service/KakaoOauthService.java | 49 ------- .../domain/auth/service/OauthService.java | 62 --------- .../auth/service/PublicKeyGenerator.java | 50 ------- .../auth/utils/AppleClaimsValidator.java | 32 ----- .../domain/auth/utils/AppleJwtParser.java | 43 ------ .../domain/auth/utils/EncryptUtils.java | 27 ---- .../domain/auth/utils/SecurityUtil.java | 28 ---- .../ttubeog/domain/member/domain/Member.java | 23 +++- .../domain/repository/MemberRepository.java | 7 + .../ttubeog/domain/member/dto/MemberDto.java | 3 +- .../member/presentation/MemberController.java | 40 +++--- .../config/FeignClientConfig.java | 4 +- 47 files changed, 311 insertions(+), 960 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/controller/AuthController.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/controller/OauthController.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/Platform.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/Status.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java rename src/main/java/com/ttubeog/domain/auth/dto/{OAuthPlatformMemberResponse.java => request/KakaoLoginRequest.java} (50%) create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/AccessTokenExpiredException.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/CustomException.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/InvalidAccessTokenException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/InvalidStatusException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/NotFoundMemberException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/PlatformException.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/AuthService.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/OauthService.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java rename src/main/java/com/ttubeog/{domain/auth => global}/config/FeignClientConfig.java (93%) diff --git a/build.gradle b/build.gradle index 9da563da..daf0bbfe 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,7 @@ dependencies { implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.2' implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0' + implementation 'org.jetbrains:annotations:24.0.0' testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.3.0' implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index b7d9e893..7dfb5d80 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,8 +1,6 @@ package com.ttubeog.domain.auth.config; -import com.ttubeog.domain.auth.exception.ExceptionHandlerFilter; -import com.ttubeog.domain.auth.service.JwtTokenService; -import com.ttubeog.domain.auth.filter.JwtFilter; +import com.ttubeog.domain.auth.service.JwtTokenProvider; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.domain.MemberRole; import lombok.RequiredArgsConstructor; @@ -15,7 +13,6 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import static org.springframework.security.config.Customizer.withDefaults; @@ -23,7 +20,7 @@ @Configuration @EnableWebSecurity public class SecurityConfig { - private final JwtTokenService jwtTokenService; + private final JwtTokenProvider jwtTokenService; private final MemberService memberService; @Bean @@ -45,8 +42,6 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable()) // 기본 http 미사용 - .addFilterBefore(new JwtFilter(jwtTokenService, memberService), UsernamePasswordAuthenticationFilter.class) // JWT 필터 추가 - .addFilterBefore(new ExceptionHandlerFilter(), JwtFilter.class) // Security Filter 에서 CustomException 사용하기 위해 추가 .build(); } diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java new file mode 100644 index 00000000..1395e8f7 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java @@ -0,0 +1,29 @@ +package com.ttubeog.domain.auth.controller; + +import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; +import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; +import com.ttubeog.domain.auth.service.AuthService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "OAuth", description = "로그인") +@RestController +@RequiredArgsConstructor +@RequestMapping("/auth") +public class AuthController { + private final AuthService authService; + + @Operation(summary = "카카오 OAuth 로그인") + @PostMapping("/login/kakao") + public ResponseEntity loginKakao(@RequestBody @Valid KakaoLoginRequest request) { + OAuthTokenResponse response = authService.kakaoOAuthLogin(request); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java b/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java deleted file mode 100644 index 66c24206..00000000 --- a/src/main/java/com/ttubeog/domain/auth/controller/OauthController.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.ttubeog.domain.auth.controller; - -import com.ttubeog.domain.auth.dto.OauthRequestDto; -import com.ttubeog.domain.auth.dto.OauthResponseDto; -import com.ttubeog.domain.auth.dto.RefreshTokenResponseDto; -import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.service.OauthService; -import com.ttubeog.global.error.DefaultException; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Arrays; -import java.util.stream.Collectors; - -@Tag(name = "Oauth", description = "Oauth API") -@RestController -@RequiredArgsConstructor -@RequestMapping("/auth") -public class OauthController { - private final OauthService oauthService; - - // 카카오 로그인 - @PostMapping("/login/kakao") - public OauthResponseDto loginWithKaKao( - @RequestBody - OauthRequestDto oauthRequestDto, - HttpServletResponse response - ) { - OauthResponseDto oauthResponseDto = new OauthResponseDto(); - String accessToken = oauthService.loginWithKakao(oauthRequestDto.getAccessToken(), response); - oauthResponseDto.setAccessToken(accessToken); - return oauthResponseDto; - } - - // 애플 로그인 - @PostMapping("/login/apple") - public OauthResponseDto loginWithApple( - @RequestBody @Valid AppleLoginRequest request, - HttpServletResponse response - ) { - OauthResponseDto oauthResponseDto = new OauthResponseDto(); - String accessToken = oauthService.loginWithApple(request.getIdentityToken(), response); - oauthResponseDto.setAccessToken(accessToken); - return oauthResponseDto; - } - - // 리프레시 토큰으로 액세스토큰 재발급 - @PostMapping("/token/refresh") - public RefreshTokenResponseDto tokenRefresh(HttpServletRequest request) { - RefreshTokenResponseDto refreshTokenResponseDto = new RefreshTokenResponseDto(); - Cookie[] list = request.getCookies(); - - if (list == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); - } - - Cookie refreshTokenCookie = Arrays.stream(list).filter(cookie -> - cookie.getName().equals("refresh_token")).collect(Collectors.toList()).get(0); - - if (refreshTokenCookie == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); - } - - String accessToken = oauthService.refreshToAccessToken(refreshTokenCookie.getValue()); - refreshTokenResponseDto.setAccessToken(accessToken); - return refreshTokenResponseDto; - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/Platform.java b/src/main/java/com/ttubeog/domain/auth/domain/Platform.java new file mode 100644 index 00000000..8f0f4c13 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/Platform.java @@ -0,0 +1,29 @@ +package com.ttubeog.domain.auth.domain; + + +import com.ttubeog.domain.auth.exception.PlatformException; +import com.ttubeog.global.error.DefaultException; +import com.ttubeog.global.payload.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Arrays; +import java.util.Objects; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public enum Platform { + APPLE("apple"), + KAKAO("kakao"); + + private String value; + + public static Platform from(String value) { + return Arrays.stream(values()) + .filter(it -> Objects.equals(it.value, value)) + .findFirst() + .orElseThrow(PlatformException::new); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/Status.java b/src/main/java/com/ttubeog/domain/auth/domain/Status.java new file mode 100644 index 00000000..3406f142 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/Status.java @@ -0,0 +1,26 @@ +package com.ttubeog.domain.auth.domain; + +import com.ttubeog.domain.auth.exception.InvalidStatusException; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Arrays; +import java.util.Objects; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public enum Status { + ACTIVE("active"), + INACTIVE("inactive"); + + private String value; + + public static Status from(String value) { + return Arrays.stream(values()) + .filter(it -> Objects.equals(it.value, value)) + .findFirst() + .orElseThrow(InvalidStatusException::new); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java deleted file mode 100644 index 7b7ea9b0..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/OauthRequestDto.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ttubeog.domain.auth.dto; - -import lombok.Getter; - -@Getter -public class OauthRequestDto { - private String accessToken; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java deleted file mode 100644 index f512778a..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/OauthResponseDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.dto; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class OauthResponseDto { - private String accessToken; - private String refreshToken; - private boolean early; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java b/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java deleted file mode 100644 index dfaa7798..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/RefreshTokenResponseDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ttubeog.domain.auth.dto; - - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class RefreshTokenResponseDto { - private String accessToken; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java deleted file mode 100644 index fe168823..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleAuthRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -public class AppleAuthRequest { -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java deleted file mode 100644 index 58a6fc3a..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleEventResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -public class AppleEventResponse { -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java deleted file mode 100644 index e8c7aa79..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleLoginRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import jakarta.validation.constraints.NotBlank; -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class AppleLoginRequest { -// private String state; -// private String authorizationCode; - @NotBlank(message = "1012: 공백일 수 없습니다.") - private String identityToken; -// private AppleUser appleUser; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java deleted file mode 100644 index 5525564f..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKey.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -public class ApplePublicKey { - - private String kty; - private String kid; - private String use; - private String alg; - private String n; - private String e; -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java deleted file mode 100644 index 51d3be94..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/ApplePublicKeyResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.naming.AuthenticationException; -import java.util.List; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -public class ApplePublicKeyResponse { - private List keys; - - public ApplePublicKey getMatchedKey(String kid, String alg) { - return keys.stream() - .filter(key -> key.getKid().equals(kid) && key.getAlg().equals(alg)) - .findAny() - .orElseThrow(() -> new CustomException(ErrorCode.INVALID_JWT_ALG_KID)); - } -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java deleted file mode 100644 index 7aecb7b5..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/AppleUser.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class AppleUser { - private String email; - private Name name; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java b/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java deleted file mode 100644 index 7e8e0ba4..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/apple/Name.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.dto.apple; - -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class Name { - private String firstName; - private String lastName; -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java deleted file mode 100644 index a05caecf..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/kakao/KakaoInfoDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ttubeog.domain.auth.dto.kakao; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Map; - -@Getter -@AllArgsConstructor -public class KakaoInfoDto { - private Long id; - private String email; - - public KakaoInfoDto(Map info) { - this.id = info.get("id") != null ? Long.valueOf(info.get("id").toString()) : null; - this.email = info.get("email") != null - ? info.get("email").toString() : ""; - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java similarity index 50% rename from src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java rename to src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java index 52c2689c..38583709 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/OAuthPlatformMemberResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java @@ -1,14 +1,18 @@ -package com.ttubeog.domain.auth.dto; +package com.ttubeog.domain.auth.dto.request; +import jakarta.validation.constraints.NotBlank; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class OAuthPlatformMemberResponse { - private String platformId; +@Getter +public class KakaoLoginRequest { + @NotBlank(message = "1012:공백일 수 없습니다.") private String email; + + @NotBlank(message = "1012:공백일 수 없습니다.") + private String platformId; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java new file mode 100644 index 00000000..2176480f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.auth.dto.response; + +import lombok.*; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@ToString +public class OAuthTokenResponse { + + private String accessToken; +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/AccessTokenExpiredException.java b/src/main/java/com/ttubeog/domain/auth/exception/AccessTokenExpiredException.java new file mode 100644 index 00000000..0b21401e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/AccessTokenExpiredException.java @@ -0,0 +1,6 @@ +package com.ttubeog.domain.auth.exception; + + +public class AccessTokenExpiredException extends RuntimeException { + public AccessTokenExpiredException() { super("Access Token 유효기간이 만료되었습니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java b/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java deleted file mode 100644 index fa142b3b..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/CustomException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ttubeog.domain.auth.exception; - - -public class CustomException extends RuntimeException { - - private final ErrorCode errorCode; - - public CustomException(ErrorCode errorCode) { - super(errorCode.getMessage()); - this.errorCode = errorCode; - } - - public ErrorCode getErrorCode() { - return errorCode; - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java deleted file mode 100644 index 995384b4..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorCode.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.ttubeog.domain.auth.exception; - -import org.springframework.http.HttpStatus; - -public enum ErrorCode { - UNAUTHORIZED("인증되지 않은 요청입니다.", HttpStatus.UNAUTHORIZED), - INVALID_ACCESS_TOKEN("유효하지 않은 액세스 토큰입니다.", HttpStatus.UNAUTHORIZED), - INVALID_REFRESH_TOKEN("유효하지 않은 리프레시 토큰입니다.", HttpStatus.UNAUTHORIZED), - BAD_REQUEST("잘못된 요청입니다.", HttpStatus.BAD_REQUEST), - NOT_EXIST_USER("존재하지 않는 유저입니다.", HttpStatus.UNAUTHORIZED), - INVALID_APPLE_OAUTH_TOKEN("Apple OAuth Identity Token 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), - PUBLIC_KEY_GENERATION_ERROR("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), - APPLE_OAUTH_TOKEN_EXPIRED("Apple OAuth 로그인 중 Identity Token 유효기간이 만료됐습니다.", HttpStatus.UNAUTHORIZED), - APPLE_OAUTH_COMMUNICATION_ERROR("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR), - INVALID_ACCESS_TOKEN_CLAIMS("Apple OAuth Claims 값이 올바르지 않습니다.", HttpStatus.UNAUTHORIZED), - INVALID_JWT_ALG_KID("Apple JWT 값의 alg, kid 정보가 올바르지 않습니다.", HttpStatus.BAD_REQUEST); - - - - private final String message; - private final HttpStatus httpStatus; - - ErrorCode(String message, HttpStatus httpStatus) { - this.message = message; - this.httpStatus = httpStatus; - } - - public String getMessage() { - return message; - } - - public HttpStatus getHttpStatus() { - return httpStatus; - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java b/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java deleted file mode 100644 index f73cc962..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/ErrorResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ttubeog.domain.auth.exception; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.*; - -@Getter -@AllArgsConstructor -public class ErrorResponse { - private static final ObjectMapper objectMapper = new ObjectMapper(); - private String errMsg; - - public String convertToJson() throws JsonProcessingException { - return objectMapper.writeValueAsString(this); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java b/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java deleted file mode 100644 index c6757df1..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/ExceptionHandlerFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ttubeog.domain.auth.exception; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.http.HttpStatus; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -public class ExceptionHandlerFilter extends OncePerRequestFilter { - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - - try { - filterChain.doFilter(request, response); - } catch (CustomException ex) { - setErrorResponse(ex.getErrorCode().getHttpStatus(), response, ex); - } catch (Exception ex) { - setErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, response, ex); - } - } - - public void setErrorResponse(HttpStatus status, HttpServletResponse response, Throwable ex) throws IOException { - logger.error("[ExceptionHandlerFilter] errMsg : " + ex.getMessage()); - - response.setStatus(status.value()); - response.setContentType("application/json; charset=UTF-8"); - - response.getWriter().write( - new ErrorResponse(ex.getMessage()) - .convertToJson() - ); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java b/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java deleted file mode 100644 index 145fbc34..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ttubeog.domain.auth.exception; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -@ControllerAdvice -public class GlobalExceptionHandler { - private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); - @ExceptionHandler(CustomException.class) - public ResponseEntity handleCustomException(CustomException ex) { - logger.error("[CustomException] errCode : " + ex.getErrorCode()); - logger.error("[CustomException] errMsg : " + ex.getMessage()); - return new ResponseEntity( - new ErrorResponse(ex.getMessage()), - ex.getErrorCode().getHttpStatus() - ); - } - - @ExceptionHandler(RuntimeException.class) - public ResponseEntity handleRuntimeException(RuntimeException ex) { - logger.error("[RuntimeException] errMsg : " + ex.getMessage()); - return new ResponseEntity( - new ErrorResponse(ex.getMessage()), - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity handleException(RuntimeException ex) { - logger.error("[Exception] errMsg : " + ex.getMessage()); - return new ResponseEntity( - new ErrorResponse(ex.getMessage()), - HttpStatus.INTERNAL_SERVER_ERROR - ); - } -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/exception/InvalidAccessTokenException.java b/src/main/java/com/ttubeog/domain/auth/exception/InvalidAccessTokenException.java new file mode 100644 index 00000000..c691215b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/InvalidAccessTokenException.java @@ -0,0 +1,6 @@ +package com.ttubeog.domain.auth.exception; + + +public class InvalidAccessTokenException extends RuntimeException { + public InvalidAccessTokenException() { super("올바르지 않은 Access Token 입니다. 다시 로그인해주세요.");} +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/InvalidStatusException.java b/src/main/java/com/ttubeog/domain/auth/exception/InvalidStatusException.java new file mode 100644 index 00000000..da0b5b04 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/InvalidStatusException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.auth.exception; + +public class InvalidStatusException extends RuntimeException { + public InvalidStatusException() { + super("회원 상태 정보가 올바르지 않습니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/NotFoundMemberException.java b/src/main/java/com/ttubeog/domain/auth/exception/NotFoundMemberException.java new file mode 100644 index 00000000..e4ef153c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/NotFoundMemberException.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.auth.exception; + + +public class NotFoundMemberException extends RuntimeException { + + public NotFoundMemberException() { + super("존재하지 않는 회원입니다."); + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/exception/PlatformException.java b/src/main/java/com/ttubeog/domain/auth/exception/PlatformException.java new file mode 100644 index 00000000..f9d5187f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/PlatformException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.auth.exception; + +public class PlatformException extends RuntimeException { + + public PlatformException(){ + super("플랫폼 에러입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java b/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java deleted file mode 100644 index d0062fdf..00000000 --- a/src/main/java/com/ttubeog/domain/auth/feign/AppleAuthClient.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ttubeog.domain.auth.feign; - -import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; - -@FeignClient(name = "appleAuthClient", url = "${apple.auth.public-key-url}") -public interface AppleAuthClient { - @GetMapping("/keys") - ApplePublicKeyResponse getAppleAuthPublicKey(); -} diff --git a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java b/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java deleted file mode 100644 index ae53a178..00000000 --- a/src/main/java/com/ttubeog/domain/auth/filter/JwtFilter.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ttubeog.domain.auth.filter; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.service.JwtTokenService; -import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.global.config.security.token.UserPrincipal; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.GenericFilterBean; - -import java.io.IOException; - -@RequiredArgsConstructor -public class JwtFilter extends GenericFilterBean { - public static final String AUTHORIZATION_HEADER = "Authorization"; - private final JwtTokenService jwtTokenService; - private final MemberService memberService; - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; - logger.info("[JwtFilter] : " + httpServletRequest.getRequestURL().toString()); - - // Swagger UI 및 관련 리소스 경로에 대한 요청인 경우 토큰 검증 생략 - if (isSwaggerPath(httpServletRequest.getRequestURI())) { - filterChain.doFilter(servletRequest, servletResponse); - return; - } - - try { - String jwt = resolveToken(httpServletRequest); - if (StringUtils.hasText(jwt) && jwtTokenService.validateToken(jwt)) { - authenticateWithJwtToken(jwt); - } - } catch (CustomException ex) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); - } - - filterChain.doFilter(servletRequest, servletResponse); - } - - private boolean isSwaggerPath(String uri) { - return uri.contains("/swagger") || - uri.contains("/v3/api-docs") || - uri.contains("/swagger-resources") || - uri.contains("/swagger-ui.html") || - uri.contains("/webjars/"); - } - - private String resolveToken(HttpServletRequest request) { - String bearerToken = request.getHeader(AUTHORIZATION_HEADER); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { - return bearerToken.substring(7); - } - return null; - } - - private void authenticateWithJwtToken(String jwt) { - Long userId = Long.valueOf(jwtTokenService.getPayload(jwt)); - MemberDto user = memberService.findById(userId); - if (user == null) { - throw new CustomException(ErrorCode.NOT_EXIST_USER); - } - UserDetails userDetails = UserPrincipal.create(user); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java b/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java deleted file mode 100644 index 7acebb76..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/AppleOAtuhUserProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.dto.OAuthPlatformMemberResponse; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.feign.AppleAuthClient; -import com.ttubeog.domain.auth.utils.AppleClaimsValidator; -import com.ttubeog.domain.auth.service.PublicKeyGenerator; -import com.ttubeog.domain.auth.utils.AppleJwtParser; -import com.ttubeog.domain.member.dto.MemberDto; -import io.jsonwebtoken.Claims; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.security.PublicKey; -import java.util.Map; - -@Component -@RequiredArgsConstructor -public class AppleOAtuhUserProvider { - private final AppleJwtParser appleJwtParser; - private final AppleAuthClient appleAuthClient; - private final PublicKeyGenerator publicKeyGenerator; - private final AppleClaimsValidator appleClaimsValidator; - - - public MemberDto getApplePlatformMember(String identityToken) { - Map headers = appleJwtParser.parseHeaders(identityToken); - ApplePublicKeyResponse applePublicKeyResponse = appleAuthClient.getAppleAuthPublicKey(); - - PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeyResponse); - - Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); - validateClaims(claims); - return new MemberDto(claims.getSubject(), claims.get("email", String.class)); - } - - private void validateClaims(Claims claims) { - if (!appleClaimsValidator.isValid(claims)) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN_CLAIMS); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java new file mode 100644 index 00000000..a06feea1 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -0,0 +1,59 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.domain.Platform; +import com.ttubeog.domain.auth.domain.Status; +import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; +import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; +import com.ttubeog.domain.auth.exception.NotFoundMemberException; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AuthService { + + private final MemberRepository memberRepository; + private final JwtTokenProvider jwtTokenProvider; + + + public OAuthTokenResponse kakaoOAuthLogin(KakaoLoginRequest request) { + + return generateOAuthTokenResponse( + Platform.KAKAO, + request.getEmail(), + request.getPlatformId() + ); + + } + + private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String email, String platformId) { + return memberRepository.findIdByPlatformAndPlatformId(platform, platformId) + .map(memberId -> { + Member findMember = memberRepository.findById(memberId) + .orElseThrow(NotFoundMemberException::new); + validateStatus(findMember); + String accessToken = issueAccessToken(findMember); + return new OAuthTokenResponse(accessToken); + }) + .orElseGet(() -> { + Member oauthMember = new Member(email, platform, platformId, Status.ACTIVE); + Member savedMember = memberRepository.save(oauthMember); + String accessToken = issueAccessToken(savedMember); + + return new OAuthTokenResponse(accessToken); + }); + } + + private String issueAccessToken(final Member findMember) { + return jwtTokenProvider.createAccessToken(findMember.getId()); + } + + private void validateStatus(final Member findMember) { + if (findMember.getStatus() != Status.ACTIVE) { + throw new InvalidMemberException(); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java new file mode 100644 index 00000000..24745dee --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java @@ -0,0 +1,65 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; +import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; +import io.jsonwebtoken.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class JwtTokenProvider { + private final String secretKey; + private final long validityAccessTokenInMilliseconds; + private final JwtParser jwtParser; + + public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey, + @Value("${jwt.access-expired-time}") + long validityAccessTokenInMilliseconds) { + this.secretKey = secretKey; + this.validityAccessTokenInMilliseconds = validityAccessTokenInMilliseconds; + this.jwtParser = Jwts.parser().setSigningKey(secretKey); + } + + public String createAccessToken(Long memberId) { + Date now = new Date(); + Date validity = new Date(now.getTime() + validityAccessTokenInMilliseconds); + + return Jwts.builder() + .setSubject(String.valueOf(memberId)) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + } + + public void validateAccessToken(String token) { + try { + jwtParser.parseClaimsJws(token); + } catch (ExpiredJwtException e) { + throw new AccessTokenExpiredException(); + } catch (JwtException e) { + throw new InvalidAccessTokenException(); + } + } + + private boolean isExpiredAccessToken (String token) { + try { + jwtParser.parseClaimsJws(token); + } catch (ExpiredJwtException e) { + return true; + } + return false; + } + + public String getPayload(String token) { + try { + return jwtParser.parseClaimsJws(token).getBody().getSubject(); + } catch (ExpiredJwtException e) { + throw new AccessTokenExpiredException(); + } catch (JwtException e) { + throw new InvalidAccessTokenException(); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java deleted file mode 100644 index fed023df..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenService.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import io.jsonwebtoken.*; -import io.jsonwebtoken.io.Decoders; -import io.jsonwebtoken.io.Encoders; -import io.jsonwebtoken.security.Keys; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import java.nio.charset.StandardCharsets; -import java.security.Key; -import java.util.Date; -import java.util.Random; - -@Service -public class JwtTokenService implements InitializingBean { - - private final String secretKey; - private final long accessTokenExpirationInSeconds; - private final long refreshTokenExpirationInSeconds; - private static Key key; - - - public JwtTokenService( - @Value("${jwt.secret-key}") String secretKey, - @Value("${jwt.access-expired-time}") long accessTokenExpirationInSeconds, - @Value("${jwt.refresh-expired-time}") long refreshTokenExpirationInSeconds - ) { - this.secretKey = secretKey; - this.accessTokenExpirationInSeconds = accessTokenExpirationInSeconds; - this.refreshTokenExpirationInSeconds = refreshTokenExpirationInSeconds; - } - - @Override - public void afterPropertiesSet() { - key = getKeyFromBase64EncodedKey(encodeBase64SecretKey(secretKey)); - } - - // JWT 토큰 생성 - public String createToken(String payload, long expireLength) { - // 토큰에 포함될 정보 - Claims claims = Jwts.claims().setSubject(payload); - // 현재 날짜와 시간 - Date now = new Date(); - // 유효기간 - Date validity = new Date(now.getTime() + expireLength); - - return Jwts.builder() - .setClaims(claims) - .setIssuedAt(now) - .setExpiration(validity) - .signWith(key, SignatureAlgorithm.HS256) // 토큰 서명 - .compact(); - } - - // 액세스 토큰 생성 - public String createAccessToken(String payload) { - return createToken(payload, accessTokenExpirationInSeconds); - } - - // 리프레시 토큰 생성 - public String createRefreshToken() { - byte[] array = new byte[7]; - new Random().nextBytes(array); - String newPayload = new String(array, StandardCharsets.UTF_8); - - return createToken(newPayload, refreshTokenExpirationInSeconds); - } - - public String getPayload(String token) { - try { - return Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody() - .getSubject(); - } catch (ExpiredJwtException e) { - return e.getClaims().getSubject(); - } catch (JwtException e) { - throw new CustomException(ErrorCode.UNAUTHORIZED); - } - } - - public boolean validateToken(String token) { - try { - Jws claimsJws = Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token); - return !claimsJws.getBody().getExpiration().before(new Date()); - } catch (JwtException | IllegalArgumentException exception) { - return false; - } - } - - - private String encodeBase64SecretKey(String secretKey) { - return Encoders.BASE64.encode(secretKey.getBytes(StandardCharsets.UTF_8)); - } - - private Key getKeyFromBase64EncodedKey(String encodedSecretKey) { - byte[] keyBytes = Decoders.BASE64.decode(encodedSecretKey); - - Key key = Keys.hmacShaKeyFor(keyBytes); - - return key; - } - - // 클라이언트 쿠키에 리프레시 토큰을 저장 - public void addRefreshTokenToCookie(String refreshToken, HttpServletResponse response) { - Long age = refreshTokenExpirationInSeconds; - Cookie cookie = new Cookie("refresh_token", refreshToken); - cookie.setPath("/"); - cookie.setMaxAge(age.intValue()); - cookie.setHttpOnly(true); - response.addCookie(cookie); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java b/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java deleted file mode 100644 index 18965dbe..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/KakaoOauthService.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.ttubeog.domain.auth.service; - - -import com.ttubeog.domain.auth.dto.kakao.KakaoInfoDto; -import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.dto.MemberDto; -import lombok.RequiredArgsConstructor; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; - -import java.util.Map; - -@RequiredArgsConstructor -@Service -public class KakaoOauthService { - private final MemberService memberService; - - // 카카오 API를 호출해서 AccessToken으로 멤버 정보를 가져오는 로직 - public Map getMemberInfoByToken(String accessToken) { - return WebClient.create() - .get() - .uri("https://kapi.kakao.com/v2/user/me") - .headers(httpHeaders -> httpHeaders.setBasicAuth(accessToken)) - .retrieve() - .bodyToMono(new ParameterizedTypeReference>() { - }) - .block(); - } - - - // 카카오 API에서 가져온 멤버 정보를 DB 저장, 업데이트 - public MemberDto getMemberProfileByToken(String accessToken) { - Map memberInfoByToken = getMemberInfoByToken(accessToken); - KakaoInfoDto kakaoInfoDto = new KakaoInfoDto(memberInfoByToken); - MemberDto memberDto = MemberDto.builder() - .id(kakaoInfoDto.getId()) - .email(kakaoInfoDto.getEmail()) - .platform("kakao") - .build(); - - if (memberService.findById(memberDto.getId()) != null) { - memberService.update(memberDto); - } else { - memberService.save(memberDto); - } - return memberDto; - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java b/src/main/java/com/ttubeog/domain/auth/service/OauthService.java deleted file mode 100644 index 86bfa36d..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/OauthService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.dto.apple.AppleLoginRequest; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.domain.repository.MemberRepository; -import com.ttubeog.domain.member.dto.MemberDto; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@RequiredArgsConstructor -@Service -public class OauthService { - private final MemberService memberService; - private final MemberRepository memberRepository; - private final JwtTokenService jwtTokenService; - private final KakaoOauthService kakaoOauthService; - private final AppleOAtuhUserProvider appleOAtuhUserProvider; - - // 카카오 로그인 - public String loginWithKakao(String accessToken, HttpServletResponse response) { - MemberDto memberDto = kakaoOauthService.getMemberProfileByToken(accessToken); - return getTokens(memberDto.getId(), response); - } - - // 애플 로그인 - public String loginWithApple(String accessToken, HttpServletResponse response) { - MemberDto memberDto = appleOAtuhUserProvider.getApplePlatformMember(accessToken); - return getTokens(memberDto.getId(), response); - } - - // 액세스, 리프레시 토큰 생성 - public String getTokens(Long id, HttpServletResponse response) { - final String accessToken = jwtTokenService.createAccessToken(id.toString()); - final String refreshToken = jwtTokenService.createRefreshToken(); - - MemberDto memberDto = memberService.findById(id); - memberDto.setRefreshToken(refreshToken); - memberService.updateRefreshToken(memberDto); - - jwtTokenService.addRefreshTokenToCookie(refreshToken, response); - return accessToken; - } - - // 리프레시 토큰을 액세스 토큰으로 갱신 - public String refreshToAccessToken(String refreshToken) { - MemberDto memberDto = memberService.findByRefreshToken(refreshToken); - - if(memberDto == null) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); - } - - if (!jwtTokenService.validateToken(refreshToken)) { - throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN); - } - - return jwtTokenService.createAccessToken(memberDto.getId().toString()); - } - -} diff --git a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java deleted file mode 100644 index b7f12e80..00000000 --- a/src/main/java/com/ttubeog/domain/auth/service/PublicKeyGenerator.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ttubeog.domain.auth.service; - -import com.ttubeog.domain.auth.dto.apple.ApplePublicKey; -import com.ttubeog.domain.auth.dto.apple.ApplePublicKeyResponse; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import org.springframework.stereotype.Component; - -import javax.naming.AuthenticationException; -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPublicKeySpec; -import java.util.Base64; -import java.util.Map; - -@Component -public class PublicKeyGenerator { - - private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; - private static final String KEY_ID_HEADER_KEY = "kid"; - private static final int POSITIVE_SIGN_NUMBER = 1; - - - public PublicKey generatePublicKey(Map headers, ApplePublicKeyResponse applePublicKeyResponse) { - ApplePublicKey applePublicKey = - applePublicKeyResponse.getMatchedKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); - - return generatePublicKeyWithApplePublicKey(applePublicKey); - } - - public PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey applePublicKey) { - byte[] nBytes = Base64.getUrlDecoder().decode(applePublicKey.getN()); - byte[] eBytes = Base64.getUrlDecoder().decode(applePublicKey.getE()); - - BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); - BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); - - RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); - - try { - KeyFactory keyFactory = KeyFactory.getInstance(applePublicKey.getKty()); - return keyFactory.generatePublic(publicKeySpec); - } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { - throw new CustomException(ErrorCode.PUBLIC_KEY_GENERATION_ERROR); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java deleted file mode 100644 index 7281abd5..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleClaimsValidator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.ttubeog.domain.auth.utils.EncryptUtils; -import io.jsonwebtoken.Claims; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -public class AppleClaimsValidator { - private static final String NONCE_KEY = "nonce"; - - private final String iss; - private final String clientId; - private final String nonce; - - - public AppleClaimsValidator( - @Value("${apple.iss}") String iss, // 애플 api 요청 경로 - @Value("${apple.bundle}") String clientId, // apple developer에 생성된 Bundle ID 값 - @Value("1234") String nonce // csrf 공격 방지를 위한 임의의 문자열 - ) { - this.iss = iss; - this.clientId = clientId; - this.nonce = EncryptUtils.encrypt(nonce); - } - - public boolean isValid(Claims claims) { - return claims.getIssuer().contains(iss) && - claims.getAudience().equals(clientId) && - claims.get(NONCE_KEY, String.class).equals(nonce); - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java deleted file mode 100644 index 2f4c66e8..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/AppleJwtParser.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.SignatureException; -import org.springframework.stereotype.Component; - -import java.security.PublicKey; -import java.util.Base64; -import java.util.Map; - -@Component -public class AppleJwtParser { - private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; - private static final int HEADER_INDEX = 0; - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - public Map parseHeaders(String identityToken) { - try { - String encodedHeader = identityToken.split(IDENTITY_TOKEN_VALUE_DELIMITER)[HEADER_INDEX]; - String decodeHeader = new String(Base64.getUrlDecoder().decode(encodedHeader)); - return OBJECT_MAPPER.readValue(decodeHeader, Map.class); - } catch (JsonProcessingException | ArrayIndexOutOfBoundsException e) { - throw new CustomException(ErrorCode.INVALID_ACCESS_TOKEN); - } - } - - public Claims parsePublicKeyAndGetClaims(String idToken, PublicKey publicKey) { - try { - return Jwts.parser() - .setSigningKey(publicKey) - .parseClaimsJws(idToken) - .getBody(); - } catch (ExpiredJwtException e) { - throw new CustomException(ErrorCode.APPLE_OAUTH_TOKEN_EXPIRED); - } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { - throw new CustomException(ErrorCode.INVALID_APPLE_OAUTH_TOKEN); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java b/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java deleted file mode 100644 index 2ae6ac11..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/EncryptUtils.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class EncryptUtils { - private static final String ENCRYPT_ALGORITHM = "SHA-256"; - private static final String FORMAT_CODE = "%02x"; - - public static String encrypt(String value) { - try { - MessageDigest sha256 = MessageDigest.getInstance(ENCRYPT_ALGORITHM); - byte[] digest = sha256.digest(value.getBytes(StandardCharsets.UTF_8)); - StringBuilder hexString = new StringBuilder(); - for (byte b : digest) { - hexString.append(String.format(FORMAT_CODE, b)); - } - return hexString.toString(); - } catch (NoSuchAlgorithmException e) { - throw new CustomException(ErrorCode.APPLE_OAUTH_COMMUNICATION_ERROR); - } - } -} diff --git a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java deleted file mode 100644 index c50c7c40..00000000 --- a/src/main/java/com/ttubeog/domain/auth/utils/SecurityUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ttubeog.domain.auth.utils; - -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.global.config.security.token.UserPrincipal; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -public class SecurityUtil { - private SecurityUtil() {} - - public static long getCurrentMemeberId() { - final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - if (authentication == null) { - throw new CustomException(ErrorCode.UNAUTHORIZED); - } - - long memberId; - - if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { - memberId = userPrincipal.getId(); - } else { - throw new CustomException(ErrorCode.BAD_REQUEST); - } - return memberId; - } -} diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 0f89f026..689abb4b 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -1,5 +1,7 @@ package com.ttubeog.domain.member.domain; +import com.ttubeog.domain.auth.domain.Platform; +import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import jakarta.validation.constraints.Email; @@ -32,13 +34,19 @@ public class Member extends BaseEntity { @Enumerated(EnumType.STRING) private MemberRole memberRole; - private String providerId; + private String platformId; + + @Enumerated(EnumType.STRING) + @Column(name = "platform") + private Platform platform; - private String platform; private String refreshToken; + @Enumerated(EnumType.STRING) + @Column(name = "status") + private Status status; @Builder - public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String providerId, String platform, String refreshToken) { + public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String platformId, Platform platform, String refreshToken) { this.id = id; this.name = name; this.email = email; @@ -46,12 +54,17 @@ public Member(Long id, String name, String email, String imageUrl, String passwo this.password = password; this.provider = provider; this.memberRole = memberRole; - this.providerId = providerId; + this.platformId = platformId; this.platform = platform; this.refreshToken = refreshToken; } - + public Member(String email, Platform platform, String platformId, Status status) { + this.email = email; + this.platform = platform; + this.platformId = platformId; + this.status = status; + } public void updateName(String name) { this.name = name; diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 258d5acb..0537fd9e 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.member.domain.repository; +import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.member.domain.Member; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.Optional; @@ -10,8 +12,13 @@ public interface MemberRepository extends JpaRepository{ Optional findByEmail(String email); + Optional findByPlatformAndPlatformId(Platform platform, String platformId); Optional findByRefreshToken(String refreshToken); Boolean existsByEmail(String email); + + @Query("select m.id from Member m where m.platform = :platform and m.platformId = :platformId") + Optional findIdByPlatformAndPlatformId(Platform platform, String platformId); + } diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java index acd7a712..51c0efb2 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.dto; +import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.member.domain.Member; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,7 +16,7 @@ public class MemberDto { private String email; private String name; private String password; - private String platform; + private Platform platform; private String refreshToken; public MemberDto(String subject, String email) { diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 4428ac7a..69f85f54 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,23 +1,13 @@ package com.ttubeog.domain.member.presentation; -import com.ttubeog.domain.auth.exception.CustomException; -import com.ttubeog.domain.auth.exception.ErrorCode; -import com.ttubeog.domain.auth.utils.SecurityUtil; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; -import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -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.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -30,20 +20,20 @@ public class MemberController { private final MemberService memberService; - @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), - }) - @GetMapping("") - public MemberDto getCurrentMember( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal - ) { - final long memberId = SecurityUtil.getCurrentMemeberId(); - MemberDto userDto = memberService.findById(memberId); - if(userDto == null) { - throw new CustomException(ErrorCode.NOT_EXIST_USER); - } - return userDto; } +// @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), +// @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), +// }) +// @GetMapping("") +// public MemberDto getCurrentMember( +// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal +// ) { +// final long memberId = SecurityUtil.getCurrentMemeberId(); +// MemberDto userDto = memberService.findById(memberId); +// if(userDto == null) { +// throw new CustomException(ErrorCode.NOT_EXIST_USER); +// } +// return userDto; } } diff --git a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java b/src/main/java/com/ttubeog/global/config/FeignClientConfig.java similarity index 93% rename from src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java rename to src/main/java/com/ttubeog/global/config/FeignClientConfig.java index 007a0faf..cfc2489d 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/FeignClientConfig.java +++ b/src/main/java/com/ttubeog/global/config/FeignClientConfig.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.config; +package com.ttubeog.global.config; import com.ttubeog.TtubeogApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; @@ -11,4 +11,4 @@ @EnableFeignClients(basePackageClasses = TtubeogApplication.class) @ImportAutoConfiguration({FeignAutoConfiguration.class, HttpClientConfiguration.class}) public class FeignClientConfig { -} +} \ No newline at end of file From ef4593a326f7499359f3d6590684012ec92aa072 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:39:30 +0900 Subject: [PATCH 093/356] Update gradle.yml --- .github/workflows/gradle.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e4b98eba..eb242665 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -104,13 +104,12 @@ jobs: aws-region: ${{ env.AWS_REGION }} # (7) 빌드 결과물을 S3 버킷에 업로드 - - name: Upload to AWS S3 - run: | - aws deploy push \ - --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - --ignore-hidden-files \ - --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ - --source . +# - name: Upload to AWS S3 + # run: | + # aws deploy push \ + # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + # --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ + # --source . # # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 # - name: Deploy to AWS EC2 from S3 From 76773b80cf73c5878c5ca426cd226cee49888f85 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 26 Jan 2024 01:44:39 +0900 Subject: [PATCH 094/356] =?UTF-8?q?[Feat]=20=EB=8F=8C=EB=A6=BC=ED=8C=90=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=83=9D=EC=84=B1=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PK가 FK라 양방향 매핑 + 영속성 전이까지 설정했습니다. --- .../domain/game/application/GameService.java | 69 ++++++++++++++++--- .../com/ttubeog/domain/game/domain/Game.java | 7 +- .../domain/game/domain/RouletteGame.java | 4 ++ ...ository.java => BasketBallRepository.java} | 2 +- .../repository/RouletteOptionRepository.java | 9 +++ .../domain/repository/RouletteRepository.java | 9 +++ .../game/dto/request/CreateRouletteReq.java | 18 +++++ .../game/dto/response/CreateRouletteRes.java | 31 +++++++++ .../game/presentation/GameController.java | 16 +++++ 9 files changed, 151 insertions(+), 14 deletions(-) rename src/main/java/com/ttubeog/domain/game/domain/repository/{BasketBallRespository.java => BasketBallRepository.java} (73%) create mode 100644 src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java create mode 100644 src/main/java/com/ttubeog/domain/game/domain/repository/RouletteRepository.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 75aa6aa2..55da8589 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -4,17 +4,14 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; -import com.ttubeog.domain.game.domain.BasketballGame; -import com.ttubeog.domain.game.domain.Game; -import com.ttubeog.domain.game.domain.GameType; -import com.ttubeog.domain.game.domain.GiftGame; -import com.ttubeog.domain.game.domain.repository.BasketBallRespository; -import com.ttubeog.domain.game.domain.repository.GameRepository; -import com.ttubeog.domain.game.domain.repository.GiftGameRepository; +import com.ttubeog.domain.game.domain.*; +import com.ttubeog.domain.game.domain.repository.*; import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; +import com.ttubeog.domain.game.dto.request.CreateRouletteReq; import com.ttubeog.domain.game.dto.response.CreateBasketballRes; import com.ttubeog.domain.game.dto.response.CreateGiftRes; +import com.ttubeog.domain.game.dto.response.CreateRouletteRes; import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -25,6 +22,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; +import java.util.List; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -34,7 +34,9 @@ public class GameService { private final MemberRepository memberRepository; private final BenefitRepository benefitRepository; private final GiftGameRepository giftGameRepository; - private final BasketBallRespository basketBallRespository; + private final BasketBallRepository basketBallRepository; + private final RouletteRepository rouletteRepository; + private final RouletteOptionRepository rouletteOptionRepository; // 선물게임 생성 @Transactional @@ -106,7 +108,7 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas .successCount(createBasketballReq.getSuccessCount()) .build(); - basketBallRespository.save(basketballGame); + basketBallRepository.save(basketballGame); CreateBasketballRes createBasketballRes = CreateBasketballRes.builder() .gameId(game.getId()) @@ -123,4 +125,53 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas return ResponseEntity.ok(apiResponse); } + + //돌림판 게임 생성 + @Transactional + public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRouletteReq createRouletteReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(createRouletteReq.getBenefitId() + ).orElseThrow(NonExistentBenefitException::new); + + //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 + if (gameRepository.existsByBenefitAndType(benefit, GameType.roulette)) { + throw new OverlappingGameException(); + } + + Game game = Game.builder() + .benefit(benefit) + .type(GameType.roulette) + .build(); + gameRepository.save(game); + + RouletteGame rouletteGame = RouletteGame.builder() + .game(game) + .optionCount(createRouletteReq.getOption()) + .build(); + rouletteRepository.save(rouletteGame); + + List contents = Arrays.asList(createRouletteReq.getContents()); + List rouletteOptionList = contents.stream().map( + content -> RouletteOption.builder() + .content(content) + .rouletteGame(rouletteGame) + .build() + ).toList(); + rouletteOptionRepository.saveAll(rouletteOptionList); + + CreateRouletteRes createRouletteRes = CreateRouletteRes.builder() + .gameId(rouletteGame.getId()) + .benefitId(benefit.getId()) + .option(rouletteGame.getOptionCount()) + .contents(contents) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(createRouletteRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index 71b25b19..724bdb9a 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -26,16 +26,15 @@ public class Game extends BaseEntity { @JoinColumn(name = "benefit_id") private Benefit benefit; - @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) private GiftGame giftGame; - @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) private BasketballGame basketballGame; - @OneToOne(mappedBy = "game", cascade = CascadeType.ALL) + @OneToOne(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) private RouletteGame rouletteGame; - @Builder public Game(GameType type, Benefit benefit) { this.type = type; diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index 11fcd768..f4c8ff73 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -14,6 +14,7 @@ @Entity @Table(name = "roulette_game") public class RouletteGame extends BaseEntity { + @Id @Column(name = "game_id", nullable = false) private Long id; @@ -26,6 +27,9 @@ public class RouletteGame extends BaseEntity { @Column(name = "option_count") private int optionCount; + @OneToMany(mappedBy = "rouletteGame", cascade = CascadeType.ALL, orphanRemoval = true) + private List rouletteOptionList; + @Builder public RouletteGame(Game game, int optionCount) { this.game = game; diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRepository.java similarity index 73% rename from src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java rename to src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRepository.java index f5a3fd5e..752f70db 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRespository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/BasketBallRepository.java @@ -5,5 +5,5 @@ import org.springframework.stereotype.Repository; @Repository -public interface BasketBallRespository extends JpaRepository { +public interface BasketBallRepository extends JpaRepository { } diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java new file mode 100644 index 00000000..de1ff0f9 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.game.domain.repository; + +import com.ttubeog.domain.game.domain.RouletteOption; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RouletteOptionRepository extends JpaRepository { +} diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteRepository.java new file mode 100644 index 00000000..1a5a610f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteRepository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.game.domain.repository; + +import com.ttubeog.domain.game.domain.RouletteGame; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RouletteRepository extends JpaRepository{ +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java new file mode 100644 index 00000000..d899011b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java @@ -0,0 +1,18 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "CreateRouletteGameRequest") +public class CreateRouletteReq { + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "옵션 수", example = "4") + private Integer option; + + @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + private String[] contents; +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java new file mode 100644 index 00000000..cec080c0 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -0,0 +1,31 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +public class CreateRouletteRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + + @Schema(description = "옵션 개수", example = "4") + private Integer option; + + @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + private List contents; + + @Builder + public CreateRouletteRes(Long gameId, Long benefitId, Integer option, List contents) { + this.gameId = gameId; + this.benefitId = benefitId; + this.option = option; + this.contents = contents; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index fe5875d4..01b80b7a 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -6,7 +6,9 @@ import com.ttubeog.domain.game.application.GameService; import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; +import com.ttubeog.domain.game.dto.request.CreateRouletteReq; import com.ttubeog.domain.game.dto.response.CreateGiftRes; +import com.ttubeog.domain.game.dto.response.CreateRouletteRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -61,4 +63,18 @@ public ResponseEntity createBasketball( return gameService.createBasketBall(userPrincipal, createBasketballReq); } + //돌림판 게임 생성 + @Operation(summary = "돌림판 게임 생성", description = "돌림판 게임을 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "돌림판 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateRouletteRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "돌림판 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PostMapping("/roulette") + public ResponseEntity createRoulette( + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody CreateRouletteReq createRouletteReq + ) throws JsonProcessingException { + return gameService.createRoulette(userPrincipal, createRouletteReq); + } + } From a5e79fb80636015ee79287f6a03a82cecdb657de Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:48:58 +0900 Subject: [PATCH 095/356] Update gradle.yml --- .github/workflows/gradle.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index eb242665..51bbeb8f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -88,6 +88,14 @@ jobs: path: | build/libs/*.jar + - uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + source: . + target: "/home/ubuntu/app/code" + deploy: name: CD with SSH From dda1f44376817543656c977ed5aa3e680d423bbf Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:54:43 +0900 Subject: [PATCH 096/356] Update gradle.yml --- .github/workflows/gradle.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 51bbeb8f..71cbf5b8 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -88,7 +88,19 @@ jobs: path: | build/libs/*.jar - - uses: appleboy/scp-action@master + - name: Remove past EC2 raw sorce dir + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo rm -rf /home/ubuntu/app/code + + + - name: Upload raw sorce to EC2 + uses: appleboy/scp-action@master with: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} From cf2b5191444142bd965e7591cc73acf2da6eec10 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 26 Jan 2024 02:06:06 +0900 Subject: [PATCH 097/356] =?UTF-8?q?[Feat]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20API=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/domain/PlatformId.java | 5 +++ .../auth/exception/BlankTokenException.java | 6 ++++ .../exception/InvalidBearerException.java | 7 ++++ .../domain/auth/service/AuthService.java | 2 +- ...thenticationPrincipalArgumentResolver.java | 34 ++++++++++++++++++ .../auth/service/AuthorizationExtractor.java | 35 ++++++++++++++++++ .../domain/auth/service/LoginInterceptor.java | 36 +++++++++++++++++++ .../domain/auth/service/LoginUserId.java | 14 ++++++++ .../service/OAuthPlatformMemberResponse.java | 15 ++++++++ .../ttubeog/domain/member/domain/Member.java | 2 +- .../config/security/auth/AuthConfig.java | 33 +++++++++++++++++ 11 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/PlatformId.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/BlankTokenException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/InvalidBearerException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java create mode 100644 src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java diff --git a/src/main/java/com/ttubeog/domain/auth/domain/PlatformId.java b/src/main/java/com/ttubeog/domain/auth/domain/PlatformId.java new file mode 100644 index 00000000..ce23b2ec --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/PlatformId.java @@ -0,0 +1,5 @@ +package com.ttubeog.domain.auth.domain; + +public enum PlatformId { + IOS, +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/BlankTokenException.java b/src/main/java/com/ttubeog/domain/auth/exception/BlankTokenException.java new file mode 100644 index 00000000..5d6e203f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/BlankTokenException.java @@ -0,0 +1,6 @@ +package com.ttubeog.domain.auth.exception; + + +public class BlankTokenException extends RuntimeException { + public BlankTokenException() { super("토큰은 공백일 수 없습니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/auth/exception/InvalidBearerException.java b/src/main/java/com/ttubeog/domain/auth/exception/InvalidBearerException.java new file mode 100644 index 00000000..056eea20 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/InvalidBearerException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.auth.exception; + +public class InvalidBearerException extends RuntimeException { + public InvalidBearerException() { + super("로그인이 필요한 서비스입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index a06feea1..610dcee6 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -39,7 +39,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String return new OAuthTokenResponse(accessToken); }) .orElseGet(() -> { - Member oauthMember = new Member(email, platform, platformId, Status.ACTIVE); + Member oauthMember = new Member(email, platform, Status.ACTIVE); Member savedMember = memberRepository.save(oauthMember); String accessToken = issueAccessToken(savedMember); diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java b/src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java new file mode 100644 index 00000000..9809a5f1 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java @@ -0,0 +1,34 @@ +package com.ttubeog.domain.auth.service; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +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; + +@Component +public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { + + private final JwtTokenProvider jwtTokenProvider; + + public AuthenticationPrincipalArgumentResolver(final JwtTokenProvider jwtTokenProvider) { + this.jwtTokenProvider = jwtTokenProvider; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(LoginUserId.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + String token = AuthorizationExtractor.extractAccessToken(request); + String payload = jwtTokenProvider.getPayload(token); + return Long.parseLong(payload); + } +} + diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java b/src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java new file mode 100644 index 00000000..6e616e2b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java @@ -0,0 +1,35 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.exception.BlankTokenException; +import com.ttubeog.domain.auth.exception.InvalidBearerException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.NoArgsConstructor; + +import java.util.Enumeration; + +@NoArgsConstructor +public class AuthorizationExtractor { + + private static final String AUTHENTICATION_TYPE = "Bearer"; + private static final String AUTHORIZATION_HEADER_KEY = "Authorization"; + private static final int START_TOKEN_INDEX = 6; + + public static String extractAccessToken(HttpServletRequest request) { + Enumeration headers = request.getHeaders(AUTHORIZATION_HEADER_KEY); + while (headers.hasMoreElements()) { + String value = headers.nextElement(); + if (value.toLowerCase().startsWith(AUTHENTICATION_TYPE.toLowerCase())) { + String extractToken = value.trim().substring(START_TOKEN_INDEX); + validateExtractToken(extractToken); + return extractToken; + } + } + throw new InvalidBearerException(); + } + + private static void validateExtractToken(String extractToken) { + if (extractToken.isBlank()) { + throw new BlankTokenException(); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java b/src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java new file mode 100644 index 00000000..47aa3a63 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java @@ -0,0 +1,36 @@ +package com.ttubeog.domain.auth.service; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class LoginInterceptor implements HandlerInterceptor { + private final JwtTokenProvider jwtTokenProvider; + + public LoginInterceptor(final JwtTokenProvider jwtTokenProvider) { + this.jwtTokenProvider = jwtTokenProvider; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if (isPreflight(request) || isSwaggerRequest(request)) { + return true; + } + + String accessToken = AuthorizationExtractor.extractAccessToken(request); + jwtTokenProvider.validateAccessToken(accessToken); + return true; + } + + private boolean isSwaggerRequest(HttpServletRequest request) { + String uri = request.getRequestURI(); + return uri.contains("swagger") || uri.contains("api-docs") || uri.contains("webjars"); + } + + private boolean isPreflight(HttpServletRequest request) { + return request.getMethod().equals(HttpMethod.OPTIONS.toString()); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java b/src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java new file mode 100644 index 00000000..7aab2dca --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.auth.service; + +import io.swagger.v3.oas.annotations.Hidden; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Hidden +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginUserId { +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java b/src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java new file mode 100644 index 00000000..49edbf5a --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.auth.service; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class OAuthPlatformMemberResponse { + + private String platformId; + private String email; +} diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 689abb4b..5b3cf637 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -59,7 +59,7 @@ public Member(Long id, String name, String email, String imageUrl, String passwo this.refreshToken = refreshToken; } - public Member(String email, Platform platform, String platformId, Status status) { + public Member(String email, Platform platform, Status status) { this.email = email; this.platform = platform; this.platformId = platformId; diff --git a/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java b/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java new file mode 100644 index 00000000..158d9edc --- /dev/null +++ b/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java @@ -0,0 +1,33 @@ +package com.ttubeog.global.config.security.auth; + +import com.ttubeog.domain.auth.service.AuthenticationPrincipalArgumentResolver; +import com.ttubeog.domain.auth.service.LoginInterceptor; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +@RequiredArgsConstructor +public class AuthConfig implements WebMvcConfigurer { + + private final LoginInterceptor loginInterceptor; + private final AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loginInterceptor) + .addPathPatterns("") + .excludePathPatterns(""); + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(authenticationPrincipalArgumentResolver); + WebMvcConfigurer.super.addArgumentResolvers(resolvers); + } +} + From 3941954b51d8cf0541c181dc6dbe30ede4cfe095 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 26 Jan 2024 02:22:19 +0900 Subject: [PATCH 098/356] =?UTF-8?q?[Feat]=20=EC=84=A0=EB=AC=BC=EB=BD=91?= =?UTF-8?q?=EA=B8=B0=20=EC=88=98=EC=A0=95=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 27 +++++++++++++++++++ .../ttubeog/domain/game/domain/GiftGame.java | 8 ++++++ .../game/dto/request/UpdateGiftReq.java | 20 ++++++++++++++ .../game/dto/response/UpdateGiftRes.java | 27 +++++++++++++++++++ .../game/exception/NonExistentException.java | 7 +++++ .../game/presentation/GameController.java | 26 +++++++++++++----- 6 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java create mode 100644 src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 55da8589..67b92a19 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -9,9 +9,12 @@ import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; import com.ttubeog.domain.game.dto.request.CreateRouletteReq; +import com.ttubeog.domain.game.dto.request.UpdateGiftReq; import com.ttubeog.domain.game.dto.response.CreateBasketballRes; import com.ttubeog.domain.game.dto.response.CreateGiftRes; import com.ttubeog.domain.game.dto.response.CreateRouletteRes; +import com.ttubeog.domain.game.dto.response.UpdateGiftRes; +import com.ttubeog.domain.game.exception.NonExistentException; import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -174,4 +177,28 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule return ResponseEntity.ok(apiResponse); } + + //선물게임 수정 + @Transactional + public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq updateGiftReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentException::new); + + giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); + giftGame.updateGiftCount(updateGiftReq.getGiftCount()); + + UpdateGiftRes updateGiftRes = UpdateGiftRes.builder() + .gameId(giftGame.getId()) + .giftCount(giftGame.getGiftCount()) + .timeLimit(giftGame.getTimeLimit()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateGiftRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index aeb7b804..13427268 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -36,4 +36,12 @@ public GiftGame(Game game, LocalTime timeLimit, Integer giftCount) { this.timeLimit = timeLimit; this.giftCount = giftCount; } + + public void updateTimeLimit(LocalTime timeLimit) { + this.timeLimit = timeLimit; + } + + public void updateGiftCount(Integer giftCount) { + this.giftCount = giftCount; + } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java new file mode 100644 index 00000000..efa9261d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -0,0 +1,20 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalTime; + +@Data +@Schema(description = "UpdateGiftGameRequest") +public class UpdateGiftReq { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "선물개수", example = "3") + private Integer giftCount; +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java new file mode 100644 index 00000000..04a26ece --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java @@ -0,0 +1,27 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalTime; + +@Data +public class UpdateGiftRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "선물개수", example = "3") + private Integer giftCount; + + @Builder + public UpdateGiftRes(Long gameId, LocalTime timeLimit, Integer giftCount) { + this.gameId = gameId; + this.timeLimit = timeLimit; + this.giftCount = giftCount; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java b/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java new file mode 100644 index 00000000..7222bcfc --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.game.exception; + +public class NonExistentException extends RuntimeException{ + + public NonExistentException() { + super("존재하지 않는 게임입니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 01b80b7a..0f4d87ae 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -1,14 +1,15 @@ package com.ttubeog.domain.game.presentation; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; -import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.game.application.GameService; import com.ttubeog.domain.game.dto.request.CreateBasketballReq; import com.ttubeog.domain.game.dto.request.CreateGiftReq; import com.ttubeog.domain.game.dto.request.CreateRouletteReq; +import com.ttubeog.domain.game.dto.request.UpdateGiftReq; +import com.ttubeog.domain.game.dto.response.CreateBasketballRes; import com.ttubeog.domain.game.dto.response.CreateGiftRes; import com.ttubeog.domain.game.dto.response.CreateRouletteRes; +import com.ttubeog.domain.game.dto.response.UpdateGiftRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -22,10 +23,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "Game", description = "Game API") @RestController @@ -52,7 +50,7 @@ public ResponseEntity createGift( //농구 게임 생성 @Operation(summary = "농구 게임 생성", description = "농구 게임을 생성합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "농구 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), + @ApiResponse(responseCode = "200", description = "농구 게임 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBasketballRes.class) ) } ), @ApiResponse(responseCode = "400", description = "농구 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PostMapping("/basketball") @@ -77,4 +75,18 @@ public ResponseEntity createRoulette( return gameService.createRoulette(userPrincipal, createRouletteReq); } + //선물 게임 생성 + @Operation(summary = "선물 게임 수정", description = "선물 게임을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "선물 게임 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateGiftRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "선물 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("/gift") + public ResponseEntity updateGift( + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateGiftReq updateGiftReq + ) throws JsonProcessingException { + return gameService.updateGift(userPrincipal, updateGiftReq); + } + } From b57fb17ef2d9aa23766a3339e58a934fa5f15dfe Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 27 Jan 2024 11:42:34 +0900 Subject: [PATCH 099/356] =?UTF-8?q?[Feat]=20=EB=86=8D=EA=B5=AC=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=88=98=EC=A0=95=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 36 ++++++++++++++----- .../domain/game/domain/BasketballGame.java | 12 +++++++ .../game/dto/request/UpdateBasketballReq.java | 23 ++++++++++++ .../dto/response/UpdateBasketballRes.java | 31 ++++++++++++++++ .../game/presentation/GameController.java | 24 ++++++++----- 5 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 67b92a19..67e0f0af 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -6,14 +6,8 @@ import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.game.domain.*; import com.ttubeog.domain.game.domain.repository.*; -import com.ttubeog.domain.game.dto.request.CreateBasketballReq; -import com.ttubeog.domain.game.dto.request.CreateGiftReq; -import com.ttubeog.domain.game.dto.request.CreateRouletteReq; -import com.ttubeog.domain.game.dto.request.UpdateGiftReq; -import com.ttubeog.domain.game.dto.response.CreateBasketballRes; -import com.ttubeog.domain.game.dto.response.CreateGiftRes; -import com.ttubeog.domain.game.dto.response.CreateRouletteRes; -import com.ttubeog.domain.game.dto.response.UpdateGiftRes; +import com.ttubeog.domain.game.dto.request.*; +import com.ttubeog.domain.game.dto.response.*; import com.ttubeog.domain.game.exception.NonExistentException; import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -201,4 +195,30 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u return ResponseEntity.ok(apiResponse); } + + //농구게임 수정 + @Transactional + public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentException::new); + + basketballGame.updateBallCount(updateBasketballReq.getBallCount()); + basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); + basketballGame.updateTimeLimit(updateBasketballReq.getTimeLimit()); + + UpdateBasketballRes updateBasketballRes = UpdateBasketballRes.builder() + .gameId(basketballGame.getId()) + .ballCount(basketballGame.getBallCount()) + .timeLimit(basketballGame.getTimeLimit()) + .successCount(basketballGame.getSuccessCount()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateBasketballRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index 6aee06a1..ddbe897f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -40,4 +40,16 @@ public BasketballGame(Game game, LocalTime timeLimit, Integer ballCount, Integer this.ballCount = ballCount; this.successCount = successCount; } + + public void updateTimeLimit(LocalTime timeLimit) { + this.timeLimit = timeLimit; + } + + public void updateBallCount(Integer ballCount) { + this.ballCount = ballCount; + } + + public void updateSuccessCount(Integer successCount) { + this.successCount = successCount; + } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java new file mode 100644 index 00000000..c5b0c2b7 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -0,0 +1,23 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalTime; + +@Data +@Schema(description = "UpdateBasketballGameRequest") +public class UpdateBasketballReq { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "공 개수", example = "10") + private Integer ballCount; + + @Schema(description = "성공 개수", example = "4") + private Integer successCount; +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java new file mode 100644 index 00000000..0675bf34 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java @@ -0,0 +1,31 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalTime; + +@Data +public class UpdateBasketballRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "공 개수", example = "10") + private Integer ballCount; + + @Schema(description = "성공 개수", example = "4") + private Integer successCount; + + @Builder + public UpdateBasketballRes(Long gameId, LocalTime timeLimit, Integer ballCount, Integer successCount) { + this.gameId = gameId; + this.timeLimit = timeLimit; + this.ballCount = ballCount; + this.successCount = successCount; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 0f4d87ae..283dccd1 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -2,14 +2,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.game.application.GameService; -import com.ttubeog.domain.game.dto.request.CreateBasketballReq; -import com.ttubeog.domain.game.dto.request.CreateGiftReq; -import com.ttubeog.domain.game.dto.request.CreateRouletteReq; -import com.ttubeog.domain.game.dto.request.UpdateGiftReq; -import com.ttubeog.domain.game.dto.response.CreateBasketballRes; -import com.ttubeog.domain.game.dto.response.CreateGiftRes; -import com.ttubeog.domain.game.dto.response.CreateRouletteRes; -import com.ttubeog.domain.game.dto.response.UpdateGiftRes; +import com.ttubeog.domain.game.dto.request.*; +import com.ttubeog.domain.game.dto.response.*; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -89,4 +83,18 @@ public ResponseEntity updateGift( return gameService.updateGift(userPrincipal, updateGiftReq); } + //농구 게임 생성 + @Operation(summary = "농구 게임 수정", description = "농구 게임을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "농구 게임 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBasketballRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "농구 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("/basketball") + public ResponseEntity updateBasketball( + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateBasketballReq updateBasketballReq + ) throws JsonProcessingException { + return gameService.updateBasketball(userPrincipal, updateBasketballReq); + } + } From 5b7ccc58e6c02c832ac68e530c996b8859247c77 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 27 Jan 2024 11:55:44 +0900 Subject: [PATCH 100/356] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=9E=84=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit game id로 삭제하면 해당 게임 종류 테이블까지 삭제됩니다. --- .../domain/game/application/GameService.java | 24 ++++++++++++++++--- .../game/exception/NonExistentException.java | 7 ------ .../exception/NonExistentGameException.java | 7 ++++++ .../game/presentation/GameController.java | 15 ++++++++++++ 4 files changed, 43 insertions(+), 10 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java create mode 100644 src/main/java/com/ttubeog/domain/game/exception/NonExistentGameException.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 67e0f0af..1ac5eb18 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -8,12 +8,13 @@ import com.ttubeog.domain.game.domain.repository.*; import com.ttubeog.domain.game.dto.request.*; import com.ttubeog.domain.game.dto.response.*; -import com.ttubeog.domain.game.exception.NonExistentException; +import com.ttubeog.domain.game.exception.NonExistentGameException; import com.ttubeog.domain.game.exception.OverlappingGameException; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -177,7 +178,7 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq updateGiftReq) throws JsonProcessingException { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentException::new); + GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); giftGame.updateGiftCount(updateGiftReq.getGiftCount()); @@ -201,7 +202,7 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentException::new); + BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); @@ -221,4 +222,21 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas return ResponseEntity.ok(apiResponse); } + + //게임 삭제 + @Transactional + public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); + + gameRepository.delete(game); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("게임을 삭제했습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java b/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java deleted file mode 100644 index 7222bcfc..00000000 --- a/src/main/java/com/ttubeog/domain/game/exception/NonExistentException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.game.exception; - -public class NonExistentException extends RuntimeException{ - - public NonExistentException() { - super("존재하지 않는 게임입니다.");} -} diff --git a/src/main/java/com/ttubeog/domain/game/exception/NonExistentGameException.java b/src/main/java/com/ttubeog/domain/game/exception/NonExistentGameException.java new file mode 100644 index 00000000..5b4dac34 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/exception/NonExistentGameException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.game.exception; + +public class NonExistentGameException extends RuntimeException{ + + public NonExistentGameException() { + super("존재하지 않는 게임입니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 283dccd1..8ee509e9 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -7,6 +7,7 @@ import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -97,4 +98,18 @@ public ResponseEntity updateBasketball( return gameService.updateBasketball(userPrincipal, updateBasketballReq); } + //게임 삭제 + @Operation(summary = "게임 삭제", description = "게임을 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @DeleteMapping("/{gameId}") + public ResponseEntity deleteGame( + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "gameId") Long gameId + ) throws JsonProcessingException { + return gameService.deleteGame(userPrincipal, gameId); + } + } From 068ea163dd42acdc7c6c796430b7f58e8b5221c7 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 27 Jan 2024 12:16:21 +0900 Subject: [PATCH 101/356] =?UTF-8?q?[Fix]=20benefit=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=98=81=EC=86=8D=EC=84=B1=20=EC=A0=84=EC=9D=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit benefit 삭제 시 해당 game까지 모두 삭제되도록 수정 --- .../java/com/ttubeog/domain/benefit/domain/Benefit.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index a702975f..90faf546 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -1,10 +1,13 @@ package com.ttubeog.domain.benefit.domain; import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.game.domain.Game; import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; import lombok.*; +import java.util.List; + @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -26,6 +29,9 @@ public class Benefit extends BaseEntity { @JoinColumn(name = "store_id") private Store store; + @OneToMany(mappedBy = "benefit", cascade = CascadeType.ALL, orphanRemoval = true) + private List game; + @Builder public Benefit(String content, BenefitType type, Store store) { this.content = content; From 8029db545361cb77d10ad73e0fa3d5c7d62da8d5 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 27 Jan 2024 16:23:25 +0900 Subject: [PATCH 102/356] =?UTF-8?q?[Feat]=20=EB=8F=8C=EB=A6=BC=ED=8C=90=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=88=98=EC=A0=95=20=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RouletteOption 도메인 수정했습니다. --- .../domain/game/application/GameService.java | 40 +++++++++++-------- .../domain/game/domain/RouletteGame.java | 16 ++++---- .../domain/game/domain/RouletteOption.java | 32 --------------- .../repository/RouletteOptionRepository.java | 9 ----- .../game/dto/request/CreateRouletteReq.java | 7 ++-- .../game/dto/request/UpdateRouletteReq.java | 17 ++++++++ .../game/dto/response/CreateRouletteRes.java | 10 ++--- .../game/dto/response/UpdateRouletteRes.java | 23 +++++++++++ .../game/presentation/GameController.java | 18 ++++++++- 9 files changed, 95 insertions(+), 77 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java delete mode 100644 src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 1ac5eb18..89556f63 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -20,9 +20,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.List; - @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -34,7 +31,6 @@ public class GameService { private final GiftGameRepository giftGameRepository; private final BasketBallRepository basketBallRepository; private final RouletteRepository rouletteRepository; - private final RouletteOptionRepository rouletteOptionRepository; // 선물게임 생성 @Transactional @@ -145,24 +141,14 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule RouletteGame rouletteGame = RouletteGame.builder() .game(game) - .optionCount(createRouletteReq.getOption()) + .options(createRouletteReq.getOptions()) .build(); rouletteRepository.save(rouletteGame); - List contents = Arrays.asList(createRouletteReq.getContents()); - List rouletteOptionList = contents.stream().map( - content -> RouletteOption.builder() - .content(content) - .rouletteGame(rouletteGame) - .build() - ).toList(); - rouletteOptionRepository.saveAll(rouletteOptionList); - CreateRouletteRes createRouletteRes = CreateRouletteRes.builder() .gameId(rouletteGame.getId()) .benefitId(benefit.getId()) - .option(rouletteGame.getOptionCount()) - .contents(contents) + .options(rouletteGame.getOptions()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -223,6 +209,28 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas return ResponseEntity.ok(apiResponse); } + //돌림판 게임 수정 + @Transactional + public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); + + rouletteGame.updateOptions(updateRouletteReq.getOptions()); + + UpdateRouletteRes updateRouletteRes = UpdateRouletteRes.builder() + .gameId(rouletteGame.getId()) + .options(rouletteGame.getOptions()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateRouletteRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + //게임 삭제 @Transactional public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index f4c8ff73..c19d3a3e 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -24,15 +24,17 @@ public class RouletteGame extends BaseEntity { @JoinColumn(name = "game_id") private Game game; - @Column(name = "option_count") - private int optionCount; - - @OneToMany(mappedBy = "rouletteGame", cascade = CascadeType.ALL, orphanRemoval = true) - private List rouletteOptionList; + @ElementCollection + @Column(name = "options") + private List options; @Builder - public RouletteGame(Game game, int optionCount) { + public RouletteGame(Game game, List options) { this.game = game; - this.optionCount = optionCount; + this.options = options; + } + + public void updateOptions(List options) { + this.options = options; } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java deleted file mode 100644 index 6f352b12..00000000 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteOption.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ttubeog.domain.game.domain; - -import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Entity -@Table(name = "roulette_option") -public class RouletteOption extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long optionId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "roulette_game_id") - private RouletteGame rouletteGame; - - @Column(name = "content") - private String content; - - @Builder - public RouletteOption(RouletteGame rouletteGame, String content) { - this.rouletteGame = rouletteGame; - this.content = content; - } -} diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java deleted file mode 100644 index de1ff0f9..00000000 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/RouletteOptionRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ttubeog.domain.game.domain.repository; - -import com.ttubeog.domain.game.domain.RouletteOption; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface RouletteOptionRepository extends JpaRepository { -} diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java index d899011b..a5fc84ad 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java @@ -3,6 +3,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data @Schema(description = "CreateRouletteGameRequest") public class CreateRouletteReq { @@ -10,9 +12,6 @@ public class CreateRouletteReq { @Schema(description = "혜택 ID", example = "1") private Long benefitId; - @Schema(description = "옵션 수", example = "4") - private Integer option; - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") - private String[] contents; + private List options; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java new file mode 100644 index 00000000..75be6d99 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java @@ -0,0 +1,17 @@ +package com.ttubeog.domain.game.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class UpdateRouletteReq { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + private List options; + +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java index cec080c0..7e22febb 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -15,17 +15,13 @@ public class CreateRouletteRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; - @Schema(description = "옵션 개수", example = "4") - private Integer option; - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") - private List contents; + private List options; @Builder - public CreateRouletteRes(Long gameId, Long benefitId, Integer option, List contents) { + public CreateRouletteRes(Long gameId, Long benefitId, List options) { this.gameId = gameId; this.benefitId = benefitId; - this.option = option; - this.contents = contents; + this.options = options; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java new file mode 100644 index 00000000..07547053 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java @@ -0,0 +1,23 @@ +package com.ttubeog.domain.game.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +public class UpdateRouletteRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + private List options; + + @Builder + public UpdateRouletteRes(Long gameId, List options) { + this.gameId = gameId; + this.options = options; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 8ee509e9..aeb7089f 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -70,7 +70,7 @@ public ResponseEntity createRoulette( return gameService.createRoulette(userPrincipal, createRouletteReq); } - //선물 게임 생성 + //선물 게임 수정 @Operation(summary = "선물 게임 수정", description = "선물 게임을 수정합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "선물 게임 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateGiftRes.class) ) } ), @@ -84,7 +84,7 @@ public ResponseEntity updateGift( return gameService.updateGift(userPrincipal, updateGiftReq); } - //농구 게임 생성 + //농구 게임 수정 @Operation(summary = "농구 게임 수정", description = "농구 게임을 수정합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "농구 게임 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBasketballRes.class) ) } ), @@ -98,6 +98,20 @@ public ResponseEntity updateBasketball( return gameService.updateBasketball(userPrincipal, updateBasketballReq); } + //돌림판 게임 수정 + @Operation(summary = "돌림판 게임 수정", description = "돌림판 게임을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "돌림판 게임 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateRouletteRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "돌림판 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("/roulette") + public ResponseEntity updateRoulette( + @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateRouletteReq updateRouletteReq + ) throws JsonProcessingException { + return gameService.updateRoulette(userPrincipal, updateRouletteReq); + } + //게임 삭제 @Operation(summary = "게임 삭제", description = "게임을 삭제합니다.") @ApiResponses(value = { From 1d9fda4e78dbe1df4d6c1d82ddff0d1880bb547f Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 27 Jan 2024 22:21:27 +0900 Subject: [PATCH 103/356] =?UTF-8?q?[Feat]=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=95=20=EC=B6=94=EA=B0=80=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/EncryptUtils.java | 24 ++++++++++++ .../domain/auth/config/SecurityConfig.java | 18 ++++++++- .../domain/auth/config/SecurityUtil.java | 25 ++++++++++++ .../domain/auth/service/AuthService.java | 3 ++ .../member/application/MemberService.java | 17 --------- .../member/presentation/MemberController.java | 38 +++++++++++-------- 6 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/config/EncryptUtils.java create mode 100644 src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/EncryptUtils.java b/src/main/java/com/ttubeog/domain/auth/config/EncryptUtils.java new file mode 100644 index 00000000..d63b0fa3 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/EncryptUtils.java @@ -0,0 +1,24 @@ +package com.ttubeog.domain.auth.config; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class EncryptUtils { + private static final String ENCRYPT_ALGORITHM = "SHA-256"; + private static final String FORMAT_CODE = "%02x"; + + public static String encrypt(String value) { + try { + MessageDigest sha256 = MessageDigest.getInstance(ENCRYPT_ALGORITHM); + byte[] digest = sha256.digest(value.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(); + for (byte b : digest) { + hexString.append(String.format(FORMAT_CODE, b)); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Apple OAuth 통신 암호화 과정 중 문제가 발생했습니다."); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 7dfb5d80..19cdece6 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -12,6 +12,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import static org.springframework.security.config.Customizer.withDefaults; @@ -20,8 +21,6 @@ @Configuration @EnableWebSecurity public class SecurityConfig { - private final JwtTokenProvider jwtTokenService; - private final MemberService memberService; @Bean public AuthenticationManager authenticationManager( @@ -45,6 +44,21 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .build(); } + @Bean + public PasswordEncoder passwordEncoder() { + return new PasswordEncoder() { + @Override + public String encode(CharSequence rawPassword) { + return EncryptUtils.encrypt(rawPassword.toString()); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return encodedPassword.equals(EncryptUtils.encrypt(rawPassword.toString())); + } + }; + } + @Bean public WebSecurityCustomizer webSecurityCustomizer(){ return web -> diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java new file mode 100644 index 00000000..8caf1d29 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java @@ -0,0 +1,25 @@ +package com.ttubeog.domain.auth.config; + + +import com.ttubeog.global.config.security.token.UserPrincipal; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +public class SecurityUtil { + private SecurityUtil() {} + + public static long getCurrentMemeberId() { + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication == null) { + } + + long memberId = 0; + + if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { + memberId = userPrincipal.getId(); + } else { + } + return memberId; + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 610dcee6..1d2f6dcb 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -9,6 +9,8 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import lombok.RequiredArgsConstructor; +import org.hibernate.procedure.ParameterMisuseException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @Service @@ -17,6 +19,7 @@ public class AuthService { private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; + private final PasswordEncoder passwordEncoder; public OAuthTokenResponse kakaoOAuthLogin(KakaoLoginRequest request) { diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 3b37058d..edad7ab3 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -47,21 +47,4 @@ public MemberDto findById(Long id) { return memberMapper.findById(id); } - public MemberDto findByRefreshToken(String refreshToken) { - Optional member = memberRepository.findByRefreshToken(refreshToken); - return member.map(MemberDto::toEntity).orElse(null); - } - - public void save(MemberDto memberDto) { - memberMapper.save(memberDto); - } - - public void update(MemberDto memberDto) { - memberMapper.update(memberDto); - } - - public void updateRefreshToken(MemberDto memberDto) { - memberMapper.updateRefreshToken(memberDto); - } - } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 69f85f54..a85b2be8 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,9 +1,17 @@ package com.ttubeog.domain.member.presentation; +import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.exception.NotFoundMemberException; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; @@ -20,20 +28,20 @@ public class MemberController { private final MemberService memberService; -// @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") -// @ApiResponses(value = { -// @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), -// @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), -// }) -// @GetMapping("") -// public MemberDto getCurrentMember( -// @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal -// ) { -// final long memberId = SecurityUtil.getCurrentMemeberId(); -// MemberDto userDto = memberService.findById(memberId); -// if(userDto == null) { -// throw new CustomException(ErrorCode.NOT_EXIST_USER); -// } -// return userDto; } + @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @GetMapping("") + public MemberDto getCurrentMember( + @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal + ) { + final long memberId = SecurityUtil.getCurrentMemeberId(); + MemberDto userDto = memberService.findById(memberId); + if(userDto == null) { + throw new NotFoundMemberException(); + } + return userDto; } } From 4572a38b74bf59387e49a58e026a2e02e68afe68 Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 27 Jan 2024 23:19:41 +0900 Subject: [PATCH 104/356] =?UTF-8?q?[Feat]=20RefreshTokenService=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 10 +++ .../domain/auth/config/RedisConfig.java | 37 +++++++++++ .../com/ttubeog/domain/auth/domain/Token.java | 35 +++++++++++ .../auth/dto/response/OAuthTokenResponse.java | 4 ++ .../InvalidRefreshTokenException.java | 8 +++ .../domain/auth/service/AuthService.java | 22 ++++++- .../auth/service/RefreshTokenService.java | 61 +++++++++++++++++++ .../ttubeog/domain/member/domain/Member.java | 9 ++- .../member/presentation/MemberController.java | 1 + 9 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/config/RedisConfig.java create mode 100644 src/main/java/com/ttubeog/domain/auth/domain/Token.java create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/InvalidRefreshTokenException.java create mode 100644 src/main/java/com/ttubeog/domain/auth/service/RefreshTokenService.java diff --git a/build.gradle b/build.gradle index daf0bbfe..febeb168 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.2' implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0' @@ -54,8 +57,15 @@ dependencies { implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.3") implementation "org.springframework.cloud:spring-cloud-starter-openfeign" + + if (System.getProperty("os.name") == "Mac OS X" && System.getProperty("os.arch") == "aarch64") { + runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.1.94.Final:osx-aarch_64") + } + } + + tasks.named('test') { useJUnitPlatform() } diff --git a/src/main/java/com/ttubeog/domain/auth/config/RedisConfig.java b/src/main/java/com/ttubeog/domain/auth/config/RedisConfig.java new file mode 100644 index 00000000..2fe724eb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/RedisConfig.java @@ -0,0 +1,37 @@ +package com.ttubeog.domain.auth.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + @Value("${redis.host}") + private String redisHost; + + @Value("${redis.port}") + private int redisPort; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort)); + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + + /* Java 기본 직렬화가 아닌 JSON 직렬화 설정 */ + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + + return redisTemplate; + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/Token.java b/src/main/java/com/ttubeog/domain/auth/domain/Token.java new file mode 100644 index 00000000..6e294edc --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/domain/Token.java @@ -0,0 +1,35 @@ +package com.ttubeog.domain.auth.domain; + +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.redis.core.TimeToLive; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Token { + @Id + private Long id; + + private String refreshToken; + + private String accessToken; + + @TimeToLive(unit = TimeUnit.MILLISECONDS) + private long expiration; + + public void setAccessToken(String newAccessToken) { + this.accessToken = newAccessToken; + } + + public static String createRefreshToken() { + return UUID.randomUUID().toString(); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java index 2176480f..b29ca4d1 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java @@ -9,4 +9,8 @@ public class OAuthTokenResponse { private String accessToken; + private String refreshToken; + private String email; + private Boolean isRegistered; + private String platformId; } diff --git a/src/main/java/com/ttubeog/domain/auth/exception/InvalidRefreshTokenException.java b/src/main/java/com/ttubeog/domain/auth/exception/InvalidRefreshTokenException.java new file mode 100644 index 00000000..3245f5eb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/InvalidRefreshTokenException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.auth.exception; + + +public class InvalidRefreshTokenException extends RuntimeException { + public InvalidRefreshTokenException() { + super("올바르지 않은 Refresh Token 입니다. 다시 로그인해주세요."); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 1d2f6dcb..b2321e29 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.auth.domain.Status; +import com.ttubeog.domain.auth.domain.Token; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.NotFoundMemberException; @@ -18,6 +19,7 @@ public class AuthService { private final MemberRepository memberRepository; + private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; private final PasswordEncoder passwordEncoder; @@ -39,14 +41,26 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String .orElseThrow(NotFoundMemberException::new); validateStatus(findMember); String accessToken = issueAccessToken(findMember); - return new OAuthTokenResponse(accessToken); + String refreshToken = issueRefreshToken(); + + refreshTokenService.saveTokenInfo(findMember.getId(), refreshToken, accessToken); + + if (!findMember.isRegisteredOAuthMember()) { + return new OAuthTokenResponse(accessToken, refreshToken, findMember.getEmail(), + false, platformId); + } + return new OAuthTokenResponse(accessToken, refreshToken, findMember.getEmail(), + true, platformId); }) .orElseGet(() -> { Member oauthMember = new Member(email, platform, Status.ACTIVE); Member savedMember = memberRepository.save(oauthMember); String accessToken = issueAccessToken(savedMember); + String refreshToken = issueRefreshToken(); + + refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); - return new OAuthTokenResponse(accessToken); + return new OAuthTokenResponse(accessToken, refreshToken, email, false, platformId); }); } @@ -54,6 +68,10 @@ private String issueAccessToken(final Member findMember) { return jwtTokenProvider.createAccessToken(findMember.getId()); } + private String issueRefreshToken() { + return Token.createRefreshToken(); + } + private void validateStatus(final Member findMember) { if (findMember.getStatus() != Status.ACTIVE) { throw new InvalidMemberException(); diff --git a/src/main/java/com/ttubeog/domain/auth/service/RefreshTokenService.java b/src/main/java/com/ttubeog/domain/auth/service/RefreshTokenService.java new file mode 100644 index 00000000..c062ef59 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/service/RefreshTokenService.java @@ -0,0 +1,61 @@ +package com.ttubeog.domain.auth.service; + +import com.ttubeog.domain.auth.domain.Token; +import com.ttubeog.domain.auth.exception.InvalidRefreshTokenException; +import com.ttubeog.domain.auth.exception.NotFoundMemberException; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +@Service +public class RefreshTokenService { + private final long validityRefreshTokenInMilliseconds; + private final MemberRepository memberRepository; + private final RedisTemplate redisTemplate; + + public RefreshTokenService(@Value("${jwt.refresh-expired-time}") + long validityRefreshTokenInMilliseconds, + MemberRepository memberRepository, + RedisTemplate redisTemplate) { + this.validityRefreshTokenInMilliseconds = validityRefreshTokenInMilliseconds; + this.memberRepository = memberRepository; + this.redisTemplate = redisTemplate; + } + + public void saveTokenInfo(Long memberId, String refreshToken, String accessToken) { + Token token = Token.builder() + .id(memberId) + .refreshToken(refreshToken) + .accessToken(accessToken) + .expiration(validityRefreshTokenInMilliseconds) + .build(); + + redisTemplate.opsForValue().set(refreshToken, token, validityRefreshTokenInMilliseconds, TimeUnit.MILLISECONDS); + } + + public Member getMemberFromRefreshToken(String refreshToken) { + Token token = findTokenByRefreshToken(refreshToken); + if (token.getExpiration() > 0) { + Long memberId = token.getId(); + return memberRepository.findById(memberId) + .orElseThrow(NotFoundMemberException::new); + } + throw new InvalidRefreshTokenException(); + } + + public Token findTokenByRefreshToken(String refreshToken) { + Token token = (Token) redisTemplate.opsForValue().get(refreshToken); + if (token != null) { + return token; + } + throw new InvalidRefreshTokenException(); + } + + public void updateToken(Token token) { + redisTemplate.opsForValue().set(token.getRefreshToken(), token, token.getExpiration(), TimeUnit.MILLISECONDS); + } +} diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 5b3cf637..e9dfa8ca 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -45,8 +45,8 @@ public class Member extends BaseEntity { @Enumerated(EnumType.STRING) @Column(name = "status") private Status status; - @Builder - public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String platformId, Platform platform, String refreshToken) { + + public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String platformId, Platform platform, String refreshToken, Status status, int reportCount) { this.id = id; this.name = name; this.email = email; @@ -57,6 +57,7 @@ public Member(Long id, String name, String email, String imageUrl, String passwo this.platformId = platformId; this.platform = platform; this.refreshToken = refreshToken; + this.status = status; } public Member(String email, Platform platform, Status status) { @@ -66,6 +67,10 @@ public Member(String email, Platform platform, Status status) { this.status = status; } + public boolean isRegisteredOAuthMember() { + return name != null; + } + public void updateName(String name) { this.name = name; } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index a85b2be8..256ce0fa 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -44,4 +44,5 @@ public MemberDto getCurrentMember( } return userDto; } + } From 622c1ddbe5ba948ca3cacc2d9d5fe5d97a2a1d66 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 28 Jan 2024 00:01:10 +0900 Subject: [PATCH 105/356] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=9E=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 35 +++++++++++++++ .../domain/game/dto/response/FindGameRes.java | 45 +++++++++++++++++++ .../game/presentation/GameController.java | 14 ++++++ 3 files changed, 94 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 89556f63..83544787 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -16,6 +16,7 @@ import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.hibernate.Hibernate; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -234,6 +235,7 @@ public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRoule //게임 삭제 @Transactional public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); @@ -247,4 +249,37 @@ public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) th return ResponseEntity.ok(apiResponse); } + //게임 조회 + @Transactional + public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); + + FindGameRes.FindGameResBuilder builder = FindGameRes.builder() + .gameId(game.getId()) + .type(game.getType()); + + if (game.getType() == GameType.basketball) { + builder.timeLimit(game.getBasketballGame().getTimeLimit()) + .ballCount(game.getBasketballGame().getBallCount()) + .successCount(game.getBasketballGame().getSuccessCount()); + } else if (game.getType() == GameType.gift) { + builder.timeLimit(game.getGiftGame().getTimeLimit()) + .giftCount(game.getGiftGame().getGiftCount()); + } else if (game.getType() == GameType.roulette) { + Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 + builder.options(game.getRouletteGame().getOptions()); + } + + FindGameRes findGameRes = builder.build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(findGameRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java new file mode 100644 index 00000000..883fb67c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -0,0 +1,45 @@ +package com.ttubeog.domain.game.dto.response; + +import com.ttubeog.domain.game.domain.GameType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalTime; +import java.util.List; + +@Data +public class FindGameRes { + + @Schema(description = "게임 ID", example = "1") + private Long gameId; + + @Schema(description = "종류", example = "roulette") + private GameType type; + + @Schema(description = "시간제한", example = "00:01:30") + private LocalTime timeLimit; + + @Schema(description = "선물개수", example = "3") + private Integer giftCount; + + @Schema(description = "공 개수", example = "10") + private Integer ballCount; + + @Schema(description = "성공 개수", example = "4") + private Integer successCount; + + @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + private List options; + + @Builder + public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { + this.gameId = gameId; + this.type = type; + this.timeLimit = timeLimit; + this.giftCount = giftCount; + this.ballCount = ballCount; + this.successCount = successCount; + this.options = options; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index aeb7089f..83725f23 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -126,4 +126,18 @@ public ResponseEntity deleteGame( return gameService.deleteGame(userPrincipal, gameId); } + //게임 조회 + @Operation(summary = "게임 조회", description = "게임을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @GetMapping("/{gameId}") + public ResponseEntity findGame( + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "gameId") Long gameId + ) throws JsonProcessingException { + return gameService.findGame(userPrincipal, gameId); + } + } From 4e6ce9b36bc83189becb7a79f3ddc3bcece43f07 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 28 Jan 2024 00:38:10 +0900 Subject: [PATCH 106/356] =?UTF-8?q?[Feat]=20=ED=98=9C=ED=83=9DID=EB=A1=9C?= =?UTF-8?q?=20=EA=B2=8C=EC=9E=84=20=EC=A1=B0=ED=9A=8C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 44 ++++++++++++++++++- .../presentation/BenefitController.java | 15 +++++++ .../domain/repository/GameRepository.java | 4 ++ .../game/presentation/GameController.java | 1 - 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 141117e2..ccef61ba 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -14,16 +14,20 @@ import com.ttubeog.domain.benefit.exception.InvalidMemberBenefitException; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; +import com.ttubeog.domain.game.domain.Game; +import com.ttubeog.domain.game.domain.GameType; +import com.ttubeog.domain.game.domain.repository.GameRepository; +import com.ttubeog.domain.game.dto.response.FindGameRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.hibernate.Hibernate; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; @@ -32,6 +36,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; @RequiredArgsConstructor @@ -43,6 +48,7 @@ public class BenefitService { private final BenefitRepository benefitRepository; private final StoreRepository storeRepository; private final MemberBenefitRepository memberBenefitRepository; + private final GameRepository gameRepository; // 혜택 생성 @Transactional @@ -228,6 +234,42 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page return ResponseEntity.ok(apiResponse); } + //혜택ID로 게임 조회 + public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); + List games = gameRepository.findAllByBenefit(benefit); + + List findGameResList = new ArrayList<>(); + for (Game game : games) { + FindGameRes.FindGameResBuilder builder = FindGameRes.builder() + .gameId(game.getId()) + .type(game.getType()); + + if (game.getType() == GameType.basketball) { + builder.timeLimit(game.getBasketballGame().getTimeLimit()) + .ballCount(game.getBasketballGame().getBallCount()) + .successCount(game.getBasketballGame().getSuccessCount()); + } else if (game.getType() == GameType.gift) { + builder.timeLimit(game.getGiftGame().getTimeLimit()) + .giftCount(game.getGiftGame().getGiftCount()); + } else if (game.getType() == GameType.roulette) { + Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 + builder.options(game.getRouletteGame().getOptions()); + } + + findGameResList.add(builder.build()); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(findGameResList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + //한달지나면 expired true로 만들기 @Transactional @Scheduled(fixedRate = 60*60000) //1시간마다 검사 diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index d901a150..2495dcc3 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; +import com.ttubeog.domain.game.dto.response.FindGameRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -113,4 +114,18 @@ public ResponseEntity findMyBenefit( ) throws JsonProcessingException { return benefitService.findMyBenefit(userPrincipal, page); } + + //혜택으로 모든 게임 조회 + @Operation(summary = "혜택으로 게임 조회", description = "혜택에 해당하는 게임을 모두 조회합니다. 최대 3개입니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "게임 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), + @ApiResponse(responseCode = "400", description = "게임 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @GetMapping("/{benefitId}/game") + public ResponseEntity findGames( + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "benefitId") Long benefitId + ) throws JsonProcessingException { + return benefitService.findGames(userPrincipal, benefitId); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java index 91e9bf73..cc73f51e 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java @@ -6,8 +6,12 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface GameRepository extends JpaRepository { Boolean existsByBenefitAndType(Benefit benefit, GameType type); + + List findAllByBenefit(Benefit benefit); } diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 83725f23..29cb6f75 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -9,7 +9,6 @@ import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; From 863a176f2bf9cc597237804b049a1661b951cafa Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 28 Jan 2024 00:56:13 +0900 Subject: [PATCH 107/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/apple/AppleClaimsValidator.java | 30 +++++++++++++ .../domain/auth/apple/AppleClient.java | 13 ++++++ .../domain/auth/apple/AppleJwtParser.java | 45 +++++++++++++++++++ .../auth/apple/AppleOAuthMemberProvider.java | 37 +++++++++++++++ .../domain/auth/apple/ApplePublicKey.java | 20 +++++++++ .../domain/auth/apple/ApplePublicKeys.java | 24 ++++++++++ .../domain/auth/apple/PublicKeyGenerator.java | 45 +++++++++++++++++++ .../domain/auth/config/RedisCacheConfig.java | 43 ++++++++++++++++++ .../auth/controller/AuthController.java | 8 ++++ .../auth/dto/request/AppleLoginRequest.java | 14 ++++++ .../domain/auth/service/AuthService.java | 12 +++++ 11 files changed, 291 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKey.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKeys.java create mode 100644 src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java create mode 100644 src/main/java/com/ttubeog/domain/auth/config/RedisCacheConfig.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/request/AppleLoginRequest.java diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java new file mode 100644 index 00000000..7f7b0cbb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java @@ -0,0 +1,30 @@ +package com.ttubeog.domain.auth.apple; + +import com.ttubeog.domain.auth.config.EncryptUtils; +import io.jsonwebtoken.Claims; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class AppleClaimsValidator { + private static final String NONCE_KEY = "nonce"; + + private final String iss; + private final String clientId; + private final String nonce; + public AppleClaimsValidator( + @Value("${apple.iss}") String iss, + @Value("${apple.bundle}") String clientId, + @Value("nonce") String nonce + ) { + this.iss = iss; + this.clientId = clientId; + this.nonce = EncryptUtils.encrypt(nonce); + } + + public boolean isValid(Claims claims) { + return claims.getIssuer().contains(iss) && + claims.getAudience().equals(clientId) && + claims.get(NONCE_KEY, String.class).equals(nonce); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java new file mode 100644 index 00000000..e0617ef8 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.auth.apple; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient(name = "apple-public-key-client", url = "https://appleid.apple.com/auth") +public interface AppleClient { + + @Cacheable(value = "oauthPublicKeyCache", cacheManager = "oauthPublicKeyCacheManager") + @GetMapping("/keys") + ApplePublicKeys getApplePublicKeys(); +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java new file mode 100644 index 00000000..d104f275 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java @@ -0,0 +1,45 @@ +package com.ttubeog.domain.auth.apple; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; +import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; +import io.jsonwebtoken.*; +import org.springframework.stereotype.Component; + +import java.security.PublicKey; +import java.util.Base64; +import java.util.Map; + +@Component +public class AppleJwtParser { + + private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; + private static final int HEADER_INDEX = 0; + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public Map parseHeaders(String identityToken) { + try { + String encodedHeader = identityToken.split(IDENTITY_TOKEN_VALUE_DELIMITER)[HEADER_INDEX]; + String decodedHeader = new String(Base64.getDecoder().decode(encodedHeader)); + return OBJECT_MAPPER.readValue(decodedHeader, Map.class); + } catch (JsonProcessingException | ArrayIndexOutOfBoundsException e) { + throw new InvalidAccessTokenException(); + } + } + + public Claims parsePublicKeyAndGetClaims(String idToken, PublicKey publicKey) { + try { + return Jwts.parser() + .setSigningKey(publicKey) + .parseClaimsJws(idToken) + .getBody(); + } catch (ExpiredJwtException e) { + throw new AccessTokenExpiredException(); + } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { + throw new InvalidAccessTokenException(); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java new file mode 100644 index 00000000..361dcb60 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java @@ -0,0 +1,37 @@ +package com.ttubeog.domain.auth.apple; + +import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; +import com.ttubeog.domain.auth.service.OAuthPlatformMemberResponse; +import io.jsonwebtoken.Claims; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.security.PublicKey; +import java.util.Map; + +@Component +@RequiredArgsConstructor +public class AppleOAuthMemberProvider { + + private final AppleJwtParser appleJwtParser; + private final AppleClient appleClient; + private final PublicKeyGenerator publicKeyGenerator; + private final AppleClaimsValidator appleClaimsValidator; + + public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) { + Map headers = appleJwtParser.parseHeaders(identityToken); + ApplePublicKeys applePublicKeys = appleClient.getApplePublicKeys(); + + PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeys); + + Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); + validateClaims(claims); + return new OAuthPlatformMemberResponse(claims.getSubject(), claims.get("email", String.class)); + } + + private void validateClaims(Claims claims) { + if (!appleClaimsValidator.isValid(claims)) { + throw new InvalidAccessTokenException(); + } + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKey.java b/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKey.java new file mode 100644 index 00000000..a03a4c2c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKey.java @@ -0,0 +1,20 @@ +package com.ttubeog.domain.auth.apple; + + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +public class ApplePublicKey { + + private String kty; + private String kid; + private String use; + private String alg; + private String n; + private String e; +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKeys.java b/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKeys.java new file mode 100644 index 00000000..18ef0a1a --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/ApplePublicKeys.java @@ -0,0 +1,24 @@ +package com.ttubeog.domain.auth.apple; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +public class ApplePublicKeys { + + private List keys; + + public ApplePublicKey getMatchesKey(String alg, String kid) { + return this.keys + .stream() + .filter(k -> k.getAlg().equals(alg) && k.getKid().equals(kid)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Apple JWT 값의 alg, kid 정보가 올바르지 않습니다.")); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java new file mode 100644 index 00000000..1364a2f0 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java @@ -0,0 +1,45 @@ +package com.ttubeog.domain.auth.apple; + +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; +import java.util.Base64; +import java.util.Map; + +@Component +public class PublicKeyGenerator { + + private static final String SIGN_ALGORITHM_HEADER_KEY = "alg"; + private static final String KEY_ID_HEADER_KEY = "kid"; + private static final int POSITIVE_SIGN_NUMBER = 1; + + public PublicKey generatePublicKey(Map headers, ApplePublicKeys applePublicKeys) { + ApplePublicKey applePublicKey = + applePublicKeys.getMatchesKey(headers.get(SIGN_ALGORITHM_HEADER_KEY), headers.get(KEY_ID_HEADER_KEY)); + + return generatePublicKeyWithApplePublicKey(applePublicKey); + } + + private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) { + byte[] nBytes = Base64.getDecoder().decode(publicKey.getN()); + byte[] eBytes = Base64.getDecoder().decode(publicKey.getE()); + + BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); + BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); + + RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); + + try { + KeyFactory keyFactory = KeyFactory.getInstance(publicKey.getKty()); + return keyFactory.generatePublic(publicKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { + throw new IllegalStateException("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다."); + } + } +} + diff --git a/src/main/java/com/ttubeog/domain/auth/config/RedisCacheConfig.java b/src/main/java/com/ttubeog/domain/auth/config/RedisCacheConfig.java new file mode 100644 index 00000000..a5379ef5 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/config/RedisCacheConfig.java @@ -0,0 +1,43 @@ +package com.ttubeog.domain.auth.config; + + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +@EnableCaching +@Configuration +public class RedisCacheConfig { + @Bean + public CacheManager oauthPublicKeyCacheManager(RedisConnectionFactory redisConnectionFactory) { + /* + * public key 갱신은 1년에 몇 번 안되므로 ttl 3일로 설정 + * 유저가 하루 1번 로그인한다고 가정, 최소 1일은 넘기는 것이 좋다고 판단 + */ + RedisCacheConfiguration redisCacheConfiguration = generateCacheConfiguration() + .entryTtl(Duration.ofDays(3L)); + return RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(redisConnectionFactory) + .cacheDefaults(redisCacheConfiguration) + .build(); + } + + private RedisCacheConfiguration generateCacheConfiguration() { + return RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith( + RedisSerializationContext.SerializationPair.fromSerializer( + new StringRedisSerializer())) + .serializeValuesWith( + RedisSerializationContext.SerializationPair.fromSerializer( + new GenericJackson2JsonRedisSerializer())); + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java index 1395e8f7..e8231bd9 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.auth.controller; +import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.service.AuthService; @@ -26,4 +27,11 @@ public ResponseEntity loginKakao(@RequestBody @Valid KakaoLo OAuthTokenResponse response = authService.kakaoOAuthLogin(request); return ResponseEntity.ok(response); } + + @Operation(summary = "애플 OAuth 로그인") + @PostMapping("/login/apple") + public ResponseEntity loginApple(@RequestBody @Valid AppleLoginRequest request) { + OAuthTokenResponse response = authService.appleOAuthLogin(request); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/request/AppleLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/request/AppleLoginRequest.java new file mode 100644 index 00000000..6e137f19 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/request/AppleLoginRequest.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.auth.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@ToString +public class AppleLoginRequest { + + @NotBlank + private String token; +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index b2321e29..6788c830 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -1,8 +1,10 @@ package com.ttubeog.domain.auth.service; +import com.ttubeog.domain.auth.apple.AppleOAuthMemberProvider; import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.auth.domain.Token; +import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.NotFoundMemberException; @@ -22,7 +24,17 @@ public class AuthService { private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; private final PasswordEncoder passwordEncoder; + private final AppleOAuthMemberProvider appleOAuthMemberProvider; + public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { + OAuthPlatformMemberResponse applePlatformMember = + appleOAuthMemberProvider.getApplePlatformMember(request.getToken()); + return generateOAuthTokenResponse( + Platform.APPLE, + applePlatformMember.getEmail(), + applePlatformMember.getPlatformId() + ); + } public OAuthTokenResponse kakaoOAuthLogin(KakaoLoginRequest request) { From 4be7ecc84891f1b5fb3f7cc5c2049d179b27c8a1 Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 28 Jan 2024 15:19:02 +0900 Subject: [PATCH 108/356] =?UTF-8?q?[Feat]=20open=20feign=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=9E=AC=EC=84=A4=EC=A0=95=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 +- .../auth/apple/AppleOAuthMemberProvider.java | 2 +- .../domain/auth/config/SecurityConfig.java | 2 - .../CustomAuthorizationRequestRepository.java | 50 ------------------- .../domain/repository/TokenRepository.java | 13 ----- .../auth/dto/response/OAuthTokenResponse.java | 2 - ...thenticationPrincipalArgumentResolver.java | 2 +- .../AuthorizationExtractor.java | 4 +- .../JwtTokenProvider.java | 2 +- .../LoginInterceptor.java | 4 +- .../{service => security}/LoginUserId.java | 2 +- .../OAuthPlatformMemberResponse.java | 2 +- .../domain/auth/service/AuthService.java | 11 ++-- .../global/config/FeignClientConfig.java | 2 - .../config/security/auth/AuthConfig.java | 4 +- ...SimpleUrlAuthenticationFailureHandler.java | 38 -------------- 16 files changed, 19 insertions(+), 125 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java delete mode 100644 src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java rename src/main/java/com/ttubeog/domain/auth/{service => security}/AuthenticationPrincipalArgumentResolver.java (97%) rename src/main/java/com/ttubeog/domain/auth/{service => security}/AuthorizationExtractor.java (91%) rename src/main/java/com/ttubeog/domain/auth/{service => security}/JwtTokenProvider.java (98%) rename src/main/java/com/ttubeog/domain/auth/{service => security}/LoginInterceptor.java (88%) rename src/main/java/com/ttubeog/domain/auth/{service => security}/LoginUserId.java (88%) rename src/main/java/com/ttubeog/domain/auth/{service => security}/OAuthPlatformMemberResponse.java (87%) delete mode 100644 src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java diff --git a/build.gradle b/build.gradle index febeb168..8420772c 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ repositories { dependencyManagement { imports { - mavenBom "org.springframework.cloud:spring-cloud-dependencies:2020.0.3" + mavenBom "org.springframework.cloud:spring-cloud-dependencies:2022.0.5" } } @@ -55,7 +55,7 @@ dependencies { // discord log back implementation 'com.github.napstr:logback-discord-appender:1.0.0' - implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.3") + implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.5") implementation "org.springframework.cloud:spring-cloud-starter-openfeign" if (System.getProperty("os.name") == "Mac OS X" && System.getProperty("os.arch") == "aarch64") { diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java index 361dcb60..d163bba3 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.auth.apple; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; -import com.ttubeog.domain.auth.service.OAuthPlatformMemberResponse; +import com.ttubeog.domain.auth.security.OAuthPlatformMemberResponse; import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 68a980ea..789ccbff 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,7 +1,5 @@ package com.ttubeog.domain.auth.config; -import com.ttubeog.domain.auth.service.JwtTokenProvider; -import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.domain.MemberRole; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java deleted file mode 100644 index 09fa9c68..00000000 --- a/src/main/java/com/ttubeog/domain/auth/domain/repository/CustomAuthorizationRequestRepository.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ttubeog.domain.auth.domain.repository; - -import com.nimbusds.oauth2.sdk.util.StringUtils; -import com.ttubeog.global.config.security.util.CustomCookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; -import org.springframework.stereotype.Repository; - -@Repository -public class CustomAuthorizationRequestRepository implements AuthorizationRequestRepository{ - public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; - public static final String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; - - private static final int cookieExpireSeconds = 60*60; - - @Override - public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { - return CustomCookie.getCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) - .map(cookie -> CustomCookie.deserialize(cookie, OAuth2AuthorizationRequest.class)) - .orElse(null); - } - - @Override - public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) { - if (authorizationRequest == null) { - CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); - return; - } - - CustomCookie.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CustomCookie.serialize(authorizationRequest), cookieExpireSeconds); - String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); - if (StringUtils.isNotBlank(redirectUriAfterLogin)) { - CustomCookie.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSeconds); - } - } - - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { - return this.loadAuthorizationRequest(request); - } - - public void removeAuthorizationRequestCookies(HttpServletRequest request, HttpServletResponse response) { - CustomCookie.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CustomCookie.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); - } - -} diff --git a/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java b/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java deleted file mode 100644 index 09249d11..00000000 --- a/src/main/java/com/ttubeog/domain/auth/domain/repository/TokenRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ttubeog.domain.auth.domain.repository; - -import com.ttubeog.domain.auth.domain.Token; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface TokenRepository extends JpaRepository { - Optional findByUserEmail(String userEmail); - Optional findByRefreshToken(String refreshToken); -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java index b29ca4d1..5c38385c 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/response/OAuthTokenResponse.java @@ -10,7 +10,5 @@ public class OAuthTokenResponse { private String accessToken; private String refreshToken; - private String email; private Boolean isRegistered; - private String platformId; } diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java b/src/main/java/com/ttubeog/domain/auth/security/AuthenticationPrincipalArgumentResolver.java similarity index 97% rename from src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java rename to src/main/java/com/ttubeog/domain/auth/security/AuthenticationPrincipalArgumentResolver.java index 9809a5f1..1f9d62cb 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthenticationPrincipalArgumentResolver.java +++ b/src/main/java/com/ttubeog/domain/auth/security/AuthenticationPrincipalArgumentResolver.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java b/src/main/java/com/ttubeog/domain/auth/security/AuthorizationExtractor.java similarity index 91% rename from src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java rename to src/main/java/com/ttubeog/domain/auth/security/AuthorizationExtractor.java index 6e616e2b..27e91923 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthorizationExtractor.java +++ b/src/main/java/com/ttubeog/domain/auth/security/AuthorizationExtractor.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; import com.ttubeog.domain.auth.exception.BlankTokenException; import com.ttubeog.domain.auth.exception.InvalidBearerException; @@ -10,7 +10,7 @@ @NoArgsConstructor public class AuthorizationExtractor { - private static final String AUTHENTICATION_TYPE = "Bearer"; + private static final String AUTHENTICATION_TYPE = "Bearer "; private static final String AUTHORIZATION_HEADER_KEY = "Authorization"; private static final int START_TOKEN_INDEX = 6; diff --git a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java similarity index 98% rename from src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java rename to src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index 24745dee..3d58d3f6 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; diff --git a/src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java b/src/main/java/com/ttubeog/domain/auth/security/LoginInterceptor.java similarity index 88% rename from src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java rename to src/main/java/com/ttubeog/domain/auth/security/LoginInterceptor.java index 47aa3a63..02fe8a24 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/LoginInterceptor.java +++ b/src/main/java/com/ttubeog/domain/auth/security/LoginInterceptor.java @@ -1,5 +1,7 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; +import com.ttubeog.domain.auth.security.AuthorizationExtractor; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpMethod; diff --git a/src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java b/src/main/java/com/ttubeog/domain/auth/security/LoginUserId.java similarity index 88% rename from src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java rename to src/main/java/com/ttubeog/domain/auth/security/LoginUserId.java index 7aab2dca..813a74ec 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/LoginUserId.java +++ b/src/main/java/com/ttubeog/domain/auth/security/LoginUserId.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; import io.swagger.v3.oas.annotations.Hidden; diff --git a/src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java b/src/main/java/com/ttubeog/domain/auth/security/OAuthPlatformMemberResponse.java similarity index 87% rename from src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java rename to src/main/java/com/ttubeog/domain/auth/security/OAuthPlatformMemberResponse.java index 49edbf5a..1872612d 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/OAuthPlatformMemberResponse.java +++ b/src/main/java/com/ttubeog/domain/auth/security/OAuthPlatformMemberResponse.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.auth.service; +package com.ttubeog.domain.auth.security; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 6788c830..663a633e 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -8,11 +8,12 @@ import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.NotFoundMemberException; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.auth.security.OAuthPlatformMemberResponse; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import lombok.RequiredArgsConstructor; -import org.hibernate.procedure.ParameterMisuseException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -58,11 +59,9 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String refreshTokenService.saveTokenInfo(findMember.getId(), refreshToken, accessToken); if (!findMember.isRegisteredOAuthMember()) { - return new OAuthTokenResponse(accessToken, refreshToken, findMember.getEmail(), - false, platformId); + return new OAuthTokenResponse(accessToken, refreshToken, false); } - return new OAuthTokenResponse(accessToken, refreshToken, findMember.getEmail(), - true, platformId); + return new OAuthTokenResponse(accessToken, refreshToken, true); }) .orElseGet(() -> { Member oauthMember = new Member(email, platform, Status.ACTIVE); @@ -72,7 +71,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); - return new OAuthTokenResponse(accessToken, refreshToken, email, false, platformId); + return new OAuthTokenResponse(accessToken, refreshToken,false); }); } diff --git a/src/main/java/com/ttubeog/global/config/FeignClientConfig.java b/src/main/java/com/ttubeog/global/config/FeignClientConfig.java index cfc2489d..8b631834 100644 --- a/src/main/java/com/ttubeog/global/config/FeignClientConfig.java +++ b/src/main/java/com/ttubeog/global/config/FeignClientConfig.java @@ -2,13 +2,11 @@ import com.ttubeog.TtubeogApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.cloud.commons.httpclient.HttpClientConfiguration; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignAutoConfiguration; import org.springframework.context.annotation.Configuration; @Configuration @EnableFeignClients(basePackageClasses = TtubeogApplication.class) -@ImportAutoConfiguration({FeignAutoConfiguration.class, HttpClientConfiguration.class}) public class FeignClientConfig { } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java b/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java index 158d9edc..4993676f 100644 --- a/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java +++ b/src/main/java/com/ttubeog/global/config/security/auth/AuthConfig.java @@ -1,7 +1,7 @@ package com.ttubeog.global.config.security.auth; -import com.ttubeog.domain.auth.service.AuthenticationPrincipalArgumentResolver; -import com.ttubeog.domain.auth.service.LoginInterceptor; +import com.ttubeog.domain.auth.security.AuthenticationPrincipalArgumentResolver; +import com.ttubeog.domain.auth.security.LoginInterceptor; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; diff --git a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java b/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java deleted file mode 100644 index a2099a52..00000000 --- a/src/main/java/com/ttubeog/global/config/security/handler/CustomSimpleUrlAuthenticationFailureHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ttubeog.global.config.security.handler; - -import com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository; -import com.ttubeog.global.config.security.util.CustomCookie; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - -import static com.ttubeog.domain.auth.domain.repository.CustomAuthorizationRequestRepository.REDIRECT_URI_PARAM_COOKIE_NAME; - -@RequiredArgsConstructor -@Component -public class CustomSimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler{ - private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository; - - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - String targetUrl = CustomCookie.getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME) - .map(Cookie::getValue) - .orElse(("/")); - - targetUrl = UriComponentsBuilder.fromUriString(targetUrl) - .queryParam("error", exception.getLocalizedMessage()) - .build().toUriString(); - - customAuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response); - - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } -} From 99b02ad75101bfcfbf0bf5a901ce866df0cc5959 Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 28 Jan 2024 23:31:06 +0900 Subject: [PATCH 109/356] =?UTF-8?q?[Feat]=20=EC=8B=9C=ED=81=90=EB=A6=AC?= =?UTF-8?q?=ED=8B=B0=20=EC=88=98=EC=A0=95=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/auth/apple/AppleClaimsValidator.java | 2 +- .../java/com/ttubeog/domain/auth/apple/AppleClient.java | 4 ++-- .../java/com/ttubeog/domain/auth/apple/AppleJwtParser.java | 7 ++++--- .../com/ttubeog/domain/auth/apple/PublicKeyGenerator.java | 7 +++++-- .../com/ttubeog/domain/auth/config/SecurityConfig.java | 4 ++-- .../java/com/ttubeog/domain/auth/config/SecurityUtil.java | 5 +++-- .../java/com/ttubeog/domain/auth/service/AuthService.java | 1 - src/main/java/com/ttubeog/domain/member/domain/Member.java | 3 +++ 8 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java index 7f7b0cbb..4a93ee22 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java @@ -15,7 +15,7 @@ public class AppleClaimsValidator { public AppleClaimsValidator( @Value("${apple.iss}") String iss, @Value("${apple.bundle}") String clientId, - @Value("nonce") String nonce + @Value("${apple.aud}") String nonce ) { this.iss = iss; this.clientId = clientId; diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java index e0617ef8..712227d2 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleClient.java @@ -4,10 +4,10 @@ import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; -@FeignClient(name = "apple-public-key-client", url = "https://appleid.apple.com/auth") +@FeignClient(name = "apple-public-key-client", url = "https://appleid.apple.com") public interface AppleClient { @Cacheable(value = "oauthPublicKeyCache", cacheManager = "oauthPublicKeyCacheManager") - @GetMapping("/keys") + @GetMapping("/auth/keys") ApplePublicKeys getApplePublicKeys(); } diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java index d104f275..b568a9a4 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleJwtParser.java @@ -17,13 +17,12 @@ public class AppleJwtParser { private static final String IDENTITY_TOKEN_VALUE_DELIMITER = "\\."; private static final int HEADER_INDEX = 0; - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public Map parseHeaders(String identityToken) { try { String encodedHeader = identityToken.split(IDENTITY_TOKEN_VALUE_DELIMITER)[HEADER_INDEX]; - String decodedHeader = new String(Base64.getDecoder().decode(encodedHeader)); + String decodedHeader = new String(Base64.getUrlDecoder().decode(encodedHeader)); return OBJECT_MAPPER.readValue(decodedHeader, Map.class); } catch (JsonProcessingException | ArrayIndexOutOfBoundsException e) { throw new InvalidAccessTokenException(); @@ -32,10 +31,12 @@ public Map parseHeaders(String identityToken) { public Claims parsePublicKeyAndGetClaims(String idToken, PublicKey publicKey) { try { - return Jwts.parser() + return Jwts.parserBuilder() .setSigningKey(publicKey) + .build() .parseClaimsJws(idToken) .getBody(); + } catch (ExpiredJwtException e) { throw new AccessTokenExpiredException(); } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { diff --git a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java index 1364a2f0..b15b3556 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.auth.apple; import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; import java.math.BigInteger; import java.security.KeyFactory; @@ -11,6 +12,7 @@ import java.util.Base64; import java.util.Map; + @Component public class PublicKeyGenerator { @@ -26,8 +28,8 @@ public PublicKey generatePublicKey(Map headers, ApplePublicKeys } private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) { - byte[] nBytes = Base64.getDecoder().decode(publicKey.getN()); - byte[] eBytes = Base64.getDecoder().decode(publicKey.getE()); + byte[] nBytes = Base64Utils.decodeFromUrlSafeString(publicKey.getN()); + byte[] eBytes = Base64Utils.decodeFromUrlSafeString(publicKey.getE()); BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); @@ -43,3 +45,4 @@ private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) } } + diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 789ccbff..451ec7de 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -31,8 +31,8 @@ public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exc .csrf((csrf) -> csrf.disable()) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/auth/login/**").permitAll() - .requestMatchers("/swagger-ui/**", "/v3/api-docs", "/swagger-resources/**").permitAll() - .requestMatchers("/user/**").hasAuthority(MemberRole.USER.getRole()) + .requestMatchers("/swagger-ui/**", "/v3/api-docs", "/swagger-resources/**", "/api/**").permitAll() +// .requestMatchers("/api/**").hasAuthority(MemberRole.USER.getRole()) .anyRequest().authenticated()) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java index 8caf1d29..c8bf6033 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.auth.config; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.config.security.token.UserPrincipal; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -16,8 +17,8 @@ public static long getCurrentMemeberId() { long memberId = 0; - if (authentication.getPrincipal() instanceof UserPrincipal userPrincipal) { - memberId = userPrincipal.getId(); + if (authentication.getPrincipal() instanceof Member member) { + memberId = member.getId(); } else { } return memberId; diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 663a633e..9fbc81ad 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -24,7 +24,6 @@ public class AuthService { private final MemberRepository memberRepository; private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; - private final PasswordEncoder passwordEncoder; private final AppleOAuthMemberProvider appleOAuthMemberProvider; public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index e9dfa8ca..366cd7ad 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -17,8 +17,11 @@ public class Member extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "member_id") private Long id; + private String oAuthId; + private String name; @Email From 36dae1b935be60f3a883f90bee657b0f878112bd Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 29 Jan 2024 00:40:49 +0900 Subject: [PATCH 110/356] =?UTF-8?q?[Feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/apple/AppleOAuthMemberProvider.java | 2 +- .../com/ttubeog/domain/auth/apple/PublicKeyGenerator.java | 7 +++---- src/main/java/com/ttubeog/domain/member/domain/Member.java | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java index d163bba3..e3b41ea9 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java @@ -25,7 +25,7 @@ public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeys); Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); - validateClaims(claims); +// validateClaims(claims); return new OAuthPlatformMemberResponse(claims.getSubject(), claims.get("email", String.class)); } diff --git a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java index b15b3556..b8115e00 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.auth.apple; import org.springframework.stereotype.Component; -import org.springframework.util.Base64Utils; import java.math.BigInteger; import java.security.KeyFactory; @@ -28,8 +27,8 @@ public PublicKey generatePublicKey(Map headers, ApplePublicKeys } private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) { - byte[] nBytes = Base64Utils.decodeFromUrlSafeString(publicKey.getN()); - byte[] eBytes = Base64Utils.decodeFromUrlSafeString(publicKey.getE()); + byte[] nBytes = Base64.getUrlDecoder().decode(publicKey.getN()); + byte[] eBytes = Base64.getUrlDecoder().decode(publicKey.getE()); BigInteger n = new BigInteger(POSITIVE_SIGN_NUMBER, nBytes); BigInteger e = new BigInteger(POSITIVE_SIGN_NUMBER, eBytes); @@ -37,7 +36,7 @@ private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); try { - KeyFactory keyFactory = KeyFactory.getInstance(publicKey.getKty()); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(publicKeySpec); } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { throw new IllegalStateException("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다."); diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 366cd7ad..59cb5ca6 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -6,7 +6,6 @@ import jakarta.persistence.*; import jakarta.validation.constraints.Email; import lombok.AccessLevel; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; From bca1e6770a8f0fc4274e02e12d2f8b0baf1de881 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 29 Jan 2024 01:16:30 +0900 Subject: [PATCH 111/356] =?UTF-8?q?[Feat]=20=ED=86=A0=ED=81=B0=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/apple/AppleClaimsValidator.java | 17 +++++++---------- .../auth/apple/AppleOAuthMemberProvider.java | 2 +- .../domain/auth/apple/PublicKeyGenerator.java | 3 +-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java index 4a93ee22..ea647a07 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleClaimsValidator.java @@ -7,24 +7,21 @@ @Component public class AppleClaimsValidator { - private static final String NONCE_KEY = "nonce"; private final String iss; - private final String clientId; - private final String nonce; + private final String aud; + public AppleClaimsValidator( @Value("${apple.iss}") String iss, - @Value("${apple.bundle}") String clientId, - @Value("${apple.aud}") String nonce - ) { + @Value("${apple.aud}") String aud + ) { this.iss = iss; - this.clientId = clientId; - this.nonce = EncryptUtils.encrypt(nonce); + this.aud = aud; } public boolean isValid(Claims claims) { return claims.getIssuer().contains(iss) && - claims.getAudience().equals(clientId) && - claims.get(NONCE_KEY, String.class).equals(nonce); + claims.getAudience().equals(aud); } } + diff --git a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java index e3b41ea9..d163bba3 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/AppleOAuthMemberProvider.java @@ -25,7 +25,7 @@ public OAuthPlatformMemberResponse getApplePlatformMember(String identityToken) PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeys); Claims claims = appleJwtParser.parsePublicKeyAndGetClaims(identityToken, publicKey); -// validateClaims(claims); + validateClaims(claims); return new OAuthPlatformMemberResponse(claims.getSubject(), claims.get("email", String.class)); } diff --git a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java index b8115e00..8ee81842 100644 --- a/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java +++ b/src/main/java/com/ttubeog/domain/auth/apple/PublicKeyGenerator.java @@ -36,8 +36,7 @@ private PublicKey generatePublicKeyWithApplePublicKey(ApplePublicKey publicKey) RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); try { - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - return keyFactory.generatePublic(publicKeySpec); + KeyFactory keyFactory = KeyFactory.getInstance(publicKey.getKty()); return keyFactory.generatePublic(publicKeySpec); } catch (NoSuchAlgorithmException | InvalidKeySpecException exception) { throw new IllegalStateException("Apple OAuth 로그인 중 public key 생성에 문제가 발생했습니다."); } From 81eb69b560da8e80c7fd3f677d842d3112b3518a Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Tue, 30 Jan 2024 14:44:16 +0900 Subject: [PATCH 112/356] =?UTF-8?q?[Feat]=20spot=20service=20createspot=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 --- .github/workflows/gradle.yml | 144 ------------------ .../dto/CreateGuestBookRequestDto.java | 2 + .../dto/request/CreateSpotRequestDto.java | 4 + .../dto/request/UpdateSpotRequestDto.java | 4 + 4 files changed, 10 insertions(+), 144 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f8b3a88b..e69de29b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,144 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle - -name: Java CI with Gradle - -on: - push: - branches: [ "dev" ] - pull_request: - branches: [ "dev" ] - -env: - AWS_REGION: ap-northeast-2 - S3_BUCKET_NAME: s3-ttubeog - CODE_DEPLOY_APPLICATION_NAME: ttubeog-codedeploy - CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: ttubeog-deploy-group - - -permissions: - contents: read - -jobs: - build: - name: Build - runs-on: ubuntu-22.04 - - steps: - # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 - - name: Checkout branch - uses: actions/checkout@v3 - - # java 버전 세팅 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'zulu' - - # git ignore한 yml 파일들 github secret에서 복사해 오기 - - name: Copy secret - env: - OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} - OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} - OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} - - OCCUPY_SECRET_DIR: ./src/main/resources - OCCUPY_DB_SECRET_DIR: ./src/main/resources/database - OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 - - OCCUPY_SECRET_DIR_FILE_NAME: application.yml - OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml - OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml - run: | - mkdir $OCCUPY_DB_SECRET_DIR - mkdir $OCCUPY_OAUTH_SECRET_DIR - - touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - - echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME - - # gradlew 실행 권한 부여 - - name: Run chmod to make gradlew executable - run: chmod +x ./gradlew - shell: bash - - # Build -> jar 파일 생성 - - name: Build with Gradle - run: ./gradlew clean build -x test - shell: bash - - - name: Upload Build artifacts - uses: actions/upload-artifact@v2 - with: - name: build-artifacts - path: | - build/libs/*.jar - - - deploy: - name: CD with SSH - needs: build - runs-on: ubuntu-22.04 - - steps: -# # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) -# - name: Configure AWS credentials -# uses: aws-actions/configure-aws-credentials@v1 -# with: -# aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} -# aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} -# aws-region: ${{ env.AWS_REGION }} -# -# # (7) 빌드 결과물을 S3 버킷에 업로드 -# - name: Upload to AWS S3 -# run: | -# aws deploy push \ -# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ -# --ignore-hidden-files \ -# --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ -# --source . -# -# # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 -# - name: Deploy to AWS EC2 from S3 -# run: | -# aws deploy create-deployment \ -# --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ -# --deployment-config-name CodeDeployDefault.AllAtOnce \ -# --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ -# --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip - - name: Download build artifacts - uses: actions/download-artifact@v2 - with: - name: build-artifacts - - # JAR 파일을 EC2에 배포하는 step - - name: SCP JAR to EC2 - uses: appleboy/scp-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - source: "*.jar" - target: "/home/ubuntu/app" - - # EC2에 SSH로 배포 커맨드를 입력하는 step - - name: Deploy SSH - uses: appleboy/ssh-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - # 기존 실행 중인 서버 종료 후 jar 파일 실행 - script: | - sudo fuser -k -n tcp 8080 - sleep 15 - sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java new file mode 100644 index 00000000..fcfa2b37 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java @@ -0,0 +1,2 @@ +package com.ttubeog.domain.guestbook.dto;public class CreateGuestBookRequestDto { +} diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java new file mode 100644 index 00000000..7156193e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.spot.dto; + +public class CreateSpotRequestDto { +} diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java new file mode 100644 index 00000000..7267df36 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.spot.dto; + +public class UpdateSpotRequestDto { +} From df077069b5b0d7cd92d28ea0f69fea8672db9fb9 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Tue, 30 Jan 2024 14:45:56 +0900 Subject: [PATCH 113/356] =?UTF-8?q?[Feat]=20spot=20service=20createspot=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 --- .github/workflows/gradle.yml | 168 ++++++++++++++++++ .../application/GuestBookService.java | 6 + .../dto/CreateGuestBookRequestDto.java | 4 +- .../domain/spot/application/SpotService.java | 33 ++++ .../domain/repository/SpotRepository.java | 4 + .../dto/request/CreateSpotRequestDto.java | 8 +- .../dto/request/UpdateSpotRequestDto.java | 2 +- .../spot/presentation/SpotController.java | 77 +++++++- .../swagger/application-springdoc.yml | 2 +- 9 files changed, 299 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e69de29b..3729bf96 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -0,0 +1,168 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "dev" ] + pull_request: + branches: [ "dev" ] + +env: + AWS_REGION: ap-northeast-2 + S3_BUCKET_NAME: s3-ttubeog + CODE_DEPLOY_APPLICATION_NAME: ttubeog-codedeploy + CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: ttubeog-deploy-group + + +permissions: + contents: read + +jobs: + build: + name: Build + runs-on: ubuntu-22.04 + + steps: + # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 + - name: Checkout branch + uses: actions/checkout@v3 + + # java 버전 세팅 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'zulu' + + # git ignore한 yml 파일들 github secret에서 복사해 오기 + - name: Copy secret + env: + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} + OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} + OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} + OCCUPY_LOGBACK_SECRET: ${{ secrets.OCCUPY_LOGBACK_SECRET }} + + OCCUPY_SECRET_DIR: ./src/main/resources + OCCUPY_DB_SECRET_DIR: ./src/main/resources/database + OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 + OCCUPY_LOGBACK_SECRET_DIR: ./src/main/resources + + OCCUPY_SECRET_DIR_FILE_NAME: application.yml + OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml + OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml + OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback-test.xml + run: | + mkdir $OCCUPY_DB_SECRET_DIR + mkdir $OCCUPY_OAUTH_SECRET_DIR + + touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + touch $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME + echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME + echo "$OCCUPY_LOGBACK_SECRET" > $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + # gradlew 실행 권한 부여 + - name: Run chmod to make gradlew executable + run: chmod +x ./gradlew + shell: bash + + # Build -> jar 파일 생성 + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + - name: Upload Build artifacts + uses: actions/upload-artifact@v2 + with: + name: build-artifacts + path: | + build/libs/*.jar + + - name: Remove past EC2 raw sorce dir + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo rm -rf /home/ubuntu/app/code + + + - name: Upload raw sorce to EC2 + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + source: . + target: "/home/ubuntu/app/code" + + + deploy: + name: CD with SSH + needs: build + runs-on: ubuntu-22.04 + + steps: + # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + # (7) 빌드 결과물을 S3 버킷에 업로드 + # - name: Upload to AWS S3 + # run: | + # aws deploy push \ + # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + # --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ + # --source . + + # # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 + # - name: Deploy to AWS EC2 from S3 + # run: | + # aws deploy create-deployment \ + # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + # --deployment-config-name CodeDeployDefault.AllAtOnce \ + # --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + # --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip + - name: Download build artifacts + uses: actions/download-artifact@v2 + with: + name: build-artifacts + + # JAR 파일을 EC2에 배포하는 step + - name: SCP JAR to EC2 + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + source: "*.jar" + target: "/home/ubuntu/app" + + # EC2에 SSH로 배포 커맨드를 입력하는 step + - name: Deploy SSH + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo fuser -k -n tcp 8080 + sleep 15 + sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index c45df13d..d8c1c7b3 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.guestbook.application; +import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +11,7 @@ @Service @Transactional(readOnly = true) public class GuestBookService { + public ResponseEntity createGuestBook(UserPrincipal userPrincipal, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { + return null; + } } diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java index fcfa2b37..76b3fcc1 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java @@ -1,2 +1,4 @@ -package com.ttubeog.domain.guestbook.dto;public class CreateGuestBookRequestDto { +package com.ttubeog.domain.guestbook.dto; + +public class CreateGuestBookRequestDto { } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index b14e1bbc..ed72d8ec 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,6 +1,13 @@ package com.ttubeog.domain.spot.application; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; +import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +15,30 @@ @Service @Transactional(readOnly = true) public class SpotService { + + private final SpotRepository spotRepository; + private final MemberRepository memberRepository; + + public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + return null; + } + + public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Integer spotId) { + return null; + } + + public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotRequestDto updateSpotRequestDto) { + return null; + } + + public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Integer spotId) { + return null; + } + + public ResponseEntity likeSpot(UserPrincipal userPrincipal, Integer spotId) { + return null; + } } diff --git a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java index cf5920d5..4828c8d8 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java @@ -4,6 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface SpotRepository extends JpaRepository { + + Optional findByName(String name); } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 7156193e..b07a4904 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -1,4 +1,10 @@ -package com.ttubeog.domain.spot.dto; +package com.ttubeog.domain.spot.dto.request; public class CreateSpotRequestDto { + + private Long id; + + private String name; + + private Long memberId; } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 7267df36..e31fa431 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -1,4 +1,4 @@ -package com.ttubeog.domain.spot.dto; +package com.ttubeog.domain.spot.dto.request; public class UpdateSpotRequestDto { } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index bf704cd4..1372f6f6 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -1,7 +1,82 @@ package com.ttubeog.domain.spot.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.guestbook.application.GuestBookService; +import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.domain.spot.application.SpotService; +import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; +import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Spot", description = "Spot API(산책 스팟 API)") @RestController +@RequiredArgsConstructor +@RequestMapping("api/v1/spot") public class SpotController { + + private final SpotService spotService; + private final GuestBookService guestBookService; + + @Operation(summary = "산책 스팟 생성", description = "산책 스팟을 생성합니다.") + @PostMapping + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestBody CreateSpotRequestDto createSpotRequestDto + ) throws JsonProcessingException { + return spotService.createSpot(userPrincipal, createSpotRequestDto); + } + + @Operation(summary = "산책 스팟 세부 사항 조회", description = "산책 스팟의 세부 사항을 조회합니다.") + @GetMapping("/{spotId}") + public ResponseEntity findBySpotId( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId + ) throws JsonProcessingException { + return spotService.findBySpotId(userPrincipal, spotId); + } + + @Operation(summary = "산책 스팟 수정", description = "산책 스팟에 대한 정보를 수정합니다.") + @PatchMapping + public ResponseEntity updateSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestBody UpdateSpotRequestDto updateSpotRequestDto + ) throws JsonProcessingException { + return spotService.updateSpot(userPrincipal, updateSpotRequestDto); + } + + @Operation(summary = "산책 스팟 삭제", description = "산책 스팟을 삭제합니다.") + @DeleteMapping("/{spotId}") + public ResponseEntity deleteSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId + ) throws JsonProcessingException { + return spotService.deleteSpot(userPrincipal, spotId); + } + + @Operation(summary = "산책 스팟 방명록 작성", description = "산책 스팟에 종속된 방명록을 작성합니다.") + @PostMapping("/{spotId}/guestbook") + public ResponseEntity createGuestBook( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId, + @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto + ) throws JsonProcessingException { + return guestBookService.createGuestBook(userPrincipal, spotId, createGuestBookRequestDto); + } + + @Operation(summary = "산책 스팟 좋아요 누르기", description = "산책 스팟에 좋아요를 누릅니다.") + @PatchMapping("/{spotId}/likes") + public ResponseEntity likeSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId + ) throws JsonProcessingException { + return spotService.likeSpot(userPrincipal, spotId); + } } diff --git a/src/main/resources/swagger/application-springdoc.yml b/src/main/resources/swagger/application-springdoc.yml index 59bfb544..8afb1174 100644 --- a/src/main/resources/swagger/application-springdoc.yml +++ b/src/main/resources/swagger/application-springdoc.yml @@ -2,7 +2,7 @@ springdoc: default-consumes-media-type: application/json;charset=UTF-8 default-produces-media-type: application/json;charset=UTF-8 swagger-ui: - path: swagger + # path: swagger disable-swagger-default-url: true display-request-duration: true operations-sorter: method From 8b21e5ba12ad6c2cb30c24105976243bab150d23 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Tue, 30 Jan 2024 17:31:13 +0900 Subject: [PATCH 114/356] [Feat] implement basic part of image domain --- .../ttubeog/domain/image/domain/Image.java | 34 +++++++++++++++++++ .../domain/repository/ImageRepository.java | 7 ++++ 2 files changed, 41 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/image/domain/Image.java create mode 100644 src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java new file mode 100644 index 00000000..f1a67f8b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -0,0 +1,34 @@ +package com.ttubeog.domain.image.domain; + +import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.spot.domain.Spot; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Builder +@Entity +@Table(name = "image") +public class Image extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "spot_id") + private Spot spot; + + @Column(name = "image") + private String image; + + public Image(Long id, Spot spot, String image) { + this.id = id; + this.spot = spot; + this.image = image; + } +} diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java new file mode 100644 index 00000000..1e787fdc --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.image.domain.repository; + +import com.ttubeog.domain.image.domain.Image; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ImageRepository extends JpaRepository { +} From 712e9b447a13f4815a4c3798cf6ea0272669382b Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 31 Jan 2024 01:33:05 +0900 Subject: [PATCH 115/356] =?UTF-8?q?[Feat]=20=EC=95=A1=EC=84=B8=EC=8A=A4=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=EC=9C=BC=EB=A1=9C=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=20=EC=84=9C=EB=B2=84=EC=9D=98=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 11 +++- .../ttubeog/domain/auth/dto/KakaoInfoDto.java | 17 ++++++ .../auth/dto/request/KakaoLoginRequest.java | 5 +- .../auth/dto/response/KakaoTokenResponse.java | 15 +++++ .../auth/security/JwtTokenProvider.java | 29 +++++++++ .../domain/auth/service/AuthService.java | 59 ++++++++++++++++--- .../ttubeog/domain/member/domain/Member.java | 26 +++----- .../domain/repository/MemberRepository.java | 7 +++ 8 files changed, 138 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/response/KakaoTokenResponse.java diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java index e8231bd9..cf4a4e48 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java @@ -2,10 +2,13 @@ import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; +import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.auth.service.AuthService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -20,12 +23,14 @@ @RequestMapping("/auth") public class AuthController { private final AuthService authService; + private final JwtTokenProvider jwtTokenProvider; @Operation(summary = "카카오 OAuth 로그인") @PostMapping("/login/kakao") - public ResponseEntity loginKakao(@RequestBody @Valid KakaoLoginRequest request) { - OAuthTokenResponse response = authService.kakaoOAuthLogin(request); - return ResponseEntity.ok(response); + public KakaoTokenResponse loginKakao(@RequestBody @Valid KakaoLoginRequest kakaoLoginRequest, HttpServletRequest request) { + KakaoTokenResponse reissueTokenResponseDto = authService.kakaoOAuthLogin(kakaoLoginRequest.getAccessToken()); + + return reissueTokenResponseDto; } @Operation(summary = "애플 OAuth 로그인") diff --git a/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java new file mode 100644 index 00000000..75dca9ee --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/KakaoInfoDto.java @@ -0,0 +1,17 @@ +package com.ttubeog.domain.auth.dto; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class KakaoInfoDto { + private long id; + + @JsonCreator + public KakaoInfoDto(@JsonProperty("id") long id) { + this.id = id; + } +} diff --git a/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java index 38583709..8f5acb74 100644 --- a/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java +++ b/src/main/java/com/ttubeog/domain/auth/dto/request/KakaoLoginRequest.java @@ -11,8 +11,5 @@ @Getter public class KakaoLoginRequest { @NotBlank(message = "1012:공백일 수 없습니다.") - private String email; - - @NotBlank(message = "1012:공백일 수 없습니다.") - private String platformId; + private String accessToken; } diff --git a/src/main/java/com/ttubeog/domain/auth/dto/response/KakaoTokenResponse.java b/src/main/java/com/ttubeog/domain/auth/dto/response/KakaoTokenResponse.java new file mode 100644 index 00000000..53f852d9 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/response/KakaoTokenResponse.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.auth.dto.response; + +import lombok.*; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Builder +public class KakaoTokenResponse { + + private String accessToken; + private String refreshToken; + private Boolean isRegistered; +} diff --git a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index 3d58d3f6..2b792796 100644 --- a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; import io.jsonwebtoken.*; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -13,6 +14,8 @@ public class JwtTokenProvider { private final String secretKey; private final long validityAccessTokenInMilliseconds; private final JwtParser jwtParser; + private final long refreshTokenTime = 1L * 60 * 1000 * 2; + public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey, @Value("${jwt.access-expired-time}") @@ -34,6 +37,22 @@ public String createAccessToken(Long memberId) { .compact(); } + + public String createRereshToken(Long userId) { // 토큰 생성 + Claims claims = Jwts.claims().setSubject(String.valueOf(userId)); + + Date now = new Date(); + String token = Jwts.builder() + .setIssuedAt(now) + .setExpiration(new Date(now.getTime() + refreshTokenTime)) + .signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘, secret 값 세팅 + .compact(); + + return token; + } + + + public void validateAccessToken(String token) { try { jwtParser.parseClaimsJws(token); @@ -53,6 +72,16 @@ private boolean isExpiredAccessToken (String token) { return false; } + public String resolveToken(HttpServletRequest request) { + String tokenHeader = request.getHeader("Authentication"); + + if (tokenHeader != null && tokenHeader.startsWith("Bearer ")) { + return tokenHeader.substring(7); + } else { + throw new IllegalArgumentException("Invalid access token header"); + } + } + public String getPayload(String token) { try { return jwtParser.parseClaimsJws(token).getBody().getSubject(); diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 9fbc81ad..66a70127 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -4,8 +4,10 @@ import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.auth.domain.Token; +import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; +import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.NotFoundMemberException; import com.ttubeog.domain.auth.security.JwtTokenProvider; @@ -14,8 +16,15 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import lombok.RequiredArgsConstructor; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Map; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -25,6 +34,8 @@ public class AuthService { private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; private final AppleOAuthMemberProvider appleOAuthMemberProvider; + public RedisTemplate redisTemplate; + public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { OAuthPlatformMemberResponse applePlatformMember = @@ -36,14 +47,37 @@ public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { ); } - public OAuthTokenResponse kakaoOAuthLogin(KakaoLoginRequest request) { + public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { - return generateOAuthTokenResponse( - Platform.KAKAO, - request.getEmail(), - request.getPlatformId() - ); + Member member; + + KakaoInfoDto memberInfo = getKakaoUserInfo(accessToken); + + Optional memberData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); + + if (memberData.isEmpty()) { + member = Member.builder() + .memberNumber(String.valueOf(memberInfo.getId())) + .status(Status.ACTIVE) + .build(); + + memberRepository.save(member); + } + + Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); + + String refreshToken = "Bearer " + jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); + + KakaoTokenResponse oAuthTokenResponse = KakaoTokenResponse.builder() + .accessToken("Bearer " + jwtTokenProvider.createAccessToken( + memberLoginData.get().getId())) + .refreshToken(refreshToken) + .isRegistered(false) + .build(); + redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); + + return oAuthTokenResponse; } private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String email, String platformId) { @@ -70,7 +104,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); - return new OAuthTokenResponse(accessToken, refreshToken,false); + return new OAuthTokenResponse(accessToken, refreshToken, false); }); } @@ -87,4 +121,15 @@ private void validateStatus(final Member findMember) { throw new InvalidMemberException(); } } + + public KakaoInfoDto getKakaoUserInfo(String accessToken) { + return WebClient.create() + .get() + .uri("https://kapi.kakao.com/v2/user/me") + .headers(httpHeaders -> httpHeaders.setBearerAuth(accessToken)) + .retrieve() + .bodyToMono(new ParameterizedTypeReference() { + }) + .block(); + } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 59cb5ca6..aa76976b 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -5,13 +5,15 @@ import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; import jakarta.validation.constraints.Email; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; +@AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Getter +@Builder public class Member extends BaseEntity { @Id @@ -23,6 +25,10 @@ public class Member extends BaseEntity { private String name; + @Size(max = 45) + @NotNull + private String memberNumber; + @Email private String email; @@ -48,20 +54,6 @@ public class Member extends BaseEntity { @Column(name = "status") private Status status; - public Member(Long id, String name, String email, String imageUrl, String password, Provider provider, MemberRole memberRole, String platformId, Platform platform, String refreshToken, Status status, int reportCount) { - this.id = id; - this.name = name; - this.email = email; - this.imageUrl = imageUrl; - this.password = password; - this.provider = provider; - this.memberRole = memberRole; - this.platformId = platformId; - this.platform = platform; - this.refreshToken = refreshToken; - this.status = status; - } - public Member(String email, Platform platform, Status status) { this.email = email; this.platform = platform; diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 0537fd9e..00ee161f 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,7 +1,9 @@ package com.ttubeog.domain.member.domain.repository; import com.ttubeog.domain.auth.domain.Platform; +import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -12,6 +14,11 @@ public interface MemberRepository extends JpaRepository{ Optional findByEmail(String email); + Optional findByMemberNumber(String memberNumber); + + @Query("SELECT m.status FROM Member m WHERE m.id = :memberId") + Optional findMemberStatus(@Param("memberId") Long memberId); + Optional findByPlatformAndPlatformId(Platform platform, String platformId); Optional findByRefreshToken(String refreshToken); From c8871ff3cbb43521d440c08575cd4c61ab61c501 Mon Sep 17 00:00:00 2001 From: arinming Date: Wed, 31 Jan 2024 01:41:32 +0900 Subject: [PATCH 116/356] [Feat] kakao login success (#30) --- .../java/com/ttubeog/domain/auth/service/AuthService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 66a70127..6472462f 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -34,7 +34,7 @@ public class AuthService { private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; private final AppleOAuthMemberProvider appleOAuthMemberProvider; - public RedisTemplate redisTemplate; + private final RedisTemplate redisTemplate; public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { @@ -64,12 +64,12 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { memberRepository.save(member); } - Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); + Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); - String refreshToken = "Bearer " + jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); + String refreshToken = jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); KakaoTokenResponse oAuthTokenResponse = KakaoTokenResponse.builder() - .accessToken("Bearer " + jwtTokenProvider.createAccessToken( + .accessToken(jwtTokenProvider.createAccessToken( memberLoginData.get().getId())) .refreshToken(refreshToken) .isRegistered(false) From 7174e838fb5093fa4e1bba415ad199c281bf578b Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Wed, 31 Jan 2024 12:57:01 +0900 Subject: [PATCH 117/356] =?UTF-8?q?[Feat]=20Store=20=EC=84=B8=EB=B6=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/application/StoreService.java | 35 +++++++++++ .../store/dto/response/GetStoreDetailRes.java | 58 +++++++++++++++++++ .../store/presentation/StoreController.java | 14 +++++ 3 files changed, 107 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 6ef58de3..30518659 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; import com.ttubeog.domain.store.dto.request.UpdateStoreReq; +import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.domain.store.exception.UnathorizedMemberException; @@ -122,4 +123,38 @@ public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) return ResponseEntity.ok(apiResponse); } + + // 매장 세부사항 조회 + public ResponseEntity getStoreDetails(Long storeId) { + + Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + + // List storeBenefits = benefitRepository.findTypeByStoreId(storeId); + // Integer guestbookCount = guestBookRepository.countByStoreId(storeId); + // Integer likesCount = likesRepository.countByStoreId(storeId); + + GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() + .storeId(storeId) + .memberId(store.getMember().getId()) + .name(store.getName()) + .info(store.getInfo()) + .dongAreaId(store.getDongArea().getId()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .stars(store.getStars()) + .type(store.getType()) + //.storeBenefits(storeBenefits.stream().map(BenefitType::getType).collect(Collectors.toList())) + //.guestbookCount(guestbookCount) + //.likesCount(likesCount) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(getStoreDetailRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java new file mode 100644 index 00000000..0569082b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -0,0 +1,58 @@ +package com.ttubeog.domain.store.dto.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ttubeog.domain.benefit.domain.BenefitType; +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GetStoreDetailRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "등록 유저 ID") + private Long memberId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "별점") + private Float stars; + + @Schema(description = "업종") + private StoreType type; + + @Schema(description = "혜택 목록") + private List storeBenefits; + + @Schema(description = "방명록 수") + private Integer guestbookCount; + + @Schema(description = "좋아요 수") + private Integer likesCount; +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index f856a1fc..be6caaec 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; import com.ttubeog.domain.store.dto.request.UpdateStoreReq; +import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; @@ -70,4 +71,17 @@ public ResponseEntity deleteStore( ) { return storeService.deleteStore(userPrincipal, storeId); } + + // 매장 세부사항 조회 + @Operation(summary = "매장 세부사항 조회", description = "매장 세부사항을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 세부사항 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetStoreDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 세부사항 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/{storeId}") + public ResponseEntity getStoreDetails( + @PathVariable Long storeId + ) { + return storeService.getStoreDetails(storeId); + } } From bfd7f4ce092adf11ccd1af3b6e1a09309ca3eb7f Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 1 Feb 2024 20:44:00 +0900 Subject: [PATCH 118/356] [Feat] compare to merge --- .../domain/spot/exception/AlreadyExistsSpotException.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/spot/exception/AlreadyExistsSpotException.java diff --git a/src/main/java/com/ttubeog/domain/spot/exception/AlreadyExistsSpotException.java b/src/main/java/com/ttubeog/domain/spot/exception/AlreadyExistsSpotException.java new file mode 100644 index 00000000..b01c2170 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/exception/AlreadyExistsSpotException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.spot.exception; + +public class AlreadyExistsSpotException extends RuntimeException { + + public AlreadyExistsSpotException() { + super("이미 존재하는 산책 장소명입니다."); + } +} From b72fea114fa4df38d3a6003e00eb5ce5da891bb4 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 1 Feb 2024 20:44:24 +0900 Subject: [PATCH 119/356] [Feat] compare to merge --- .../domain/repository/ImageRepository.java | 8 ++++ .../domain/spot/application/SpotService.java | 39 +++++++++++++++++++ .../com/ttubeog/domain/spot/domain/Spot.java | 13 +++++-- .../dto/request/CreateSpotRequestDto.java | 21 +++++++++- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java index 1e787fdc..7a65d669 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -3,5 +3,13 @@ import com.ttubeog.domain.image.domain.Image; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; +import java.util.Optional; + public interface ImageRepository extends JpaRepository { + + @Override + List findAll(); + + findBySpotId(Long id); } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index ed72d8ec..f152f7cf 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,16 +1,27 @@ package com.ttubeog.domain.spot.application; +import com.ttubeog.domain.area.domain.DongArea; +import com.ttubeog.domain.area.domain.repository.DongAreaRepository; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.awt.font.ImageGraphicAttribute; +import java.util.List; +import java.util.Optional; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -18,11 +29,39 @@ public class SpotService { private final SpotRepository spotRepository; private final MemberRepository memberRepository; + private final DongAreaRepository dongAreaRepository; + private final ImageRepository imageRepository; public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + if (spotRepository.findByName(createSpotRequestDto.getName()).isPresent()) { + throw new AlreadyExistsSpotException(); + } + + Optional memberOptional = memberRepository.findById(createSpotRequestDto.getMemberId()); + Optional dongAreaOptional = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()); + List imageOptional = imageRepository.findBySpotId(createSpotRequestDto.getId()); + if (memberOptional.isPresent() && dongAreaOptional.isPresent() && imageOptional.isPresent()) { + Member member = memberOptional.get(); + DongArea dongArea = dongAreaOptional.get(); + Image image = imageOptional.get(); + + Spot spot = Spot.builder() + .member(member) + .dongArea(dongArea) + .detailAddress(createSpotRequestDto.getDetailAddress()) + .name(createSpotRequestDto.getName()) + .info(createSpotRequestDto.getInfo()) + .latitude(createSpotRequestDto.getLatitude()) + .longitude(createSpotRequestDto.getLongitude()) + .images(image) + .build(); + } + + + return null; } diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 1b479be8..043beb4d 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.member.domain.Member; import jakarta.persistence.*; import lombok.AccessLevel; @@ -11,8 +12,11 @@ import org.apache.ibatis.annotations.Many; import org.hibernate.annotations.Fetch; +import java.util.List; + @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter +@Builder @Entity @Table(name = "spot") public class Spot extends BaseEntity { @@ -33,8 +37,9 @@ public class Spot extends BaseEntity { @Column(name = "longitude") private Float longitude; - @Column(name = "image") - private String image; + @Column(name = "images") + @OneToMany(mappedBy = "spot", cascade = CascadeType.ALL, orphanRemoval = true) + private List images; @Column(name = "starts") private Float stars; @@ -50,13 +55,13 @@ public class Spot extends BaseEntity { @Column(name = "detail_address") private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, String image, Float stars, Member member, DongArea dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Float latitude, Float longitude, List images, Float stars, Member member, DongArea dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; this.latitude = latitude; this.longitude = longitude; - this.image = image; + this.images = images; this.stars = stars; this.member = member; this.dongArea = dongArea; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index b07a4904..81c1515a 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -1,10 +1,27 @@ package com.ttubeog.domain.spot.dto.request; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Builder +@AllArgsConstructor public class CreateSpotRequestDto { private Long id; - private String name; - private Long memberId; + private Long dongAreaId; + private String detailAddress; + private String info; + private Float latitude; + private Float longitude; + private List image; + private Float stars; + } From 8ac4f80ef66a3842723558ad89f9f2c48bc25fe0 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 1 Feb 2024 23:42:18 +0900 Subject: [PATCH 120/356] =?UTF-8?q?[Feat]=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EB=88=84=EB=A5=B4=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../likes/application/LikesService.java | 76 ++++++++++++++++++- .../ttubeog/domain/likes/domain/Likes.java | 29 ++++++- .../domain/repository/LikesRepository.java | 3 + .../exception/AlreadyLikesException.java | 8 ++ .../exception/NonExistentSpotException.java | 8 ++ 5 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/likes/exception/AlreadyLikesException.java create mode 100644 src/main/java/com/ttubeog/domain/spot/exception/NonExistentSpotException.java diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 8af65fdb..9417c213 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -1,11 +1,85 @@ package com.ttubeog.domain.likes.application; +import com.ttubeog.domain.likes.domain.Likes; +import com.ttubeog.domain.likes.domain.repository.LikesRepository; +import com.ttubeog.domain.likes.exception.AlreadyLikesException; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.NonExistentStoreException; +import com.ttubeog.domain.spot.exception.NonExistentSpotException; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) public class LikesService { -} + + private final MemberRepository memberRepository; + private final StoreRepository storeRepository; + private final SpotRepository spotRepository; + private final LikesRepository likesRepository; + + // 매장 좋아요 누르기 + @Transactional + public ResponseEntity likesStore(UserPrincipal userPrincipal, Long storeId) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + + if (likesRepository.existsByMemberIdAndStoreId(member.getId(), storeId)) { + throw new AlreadyLikesException(); + } + + Likes likes = Likes.builder() + .member(member) + .store(store) + .build(); + + likesRepository.save(likes); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("매장에 대한 좋아요를 눌렀습니다.")) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + // 산책스팟 좋아요 누르기 + @Transactional + public ResponseEntity likesSpot(UserPrincipal userPrincipal, Long spotId) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Spot spot = spotRepository.findById(spotId).orElseThrow(NonExistentSpotException::new); + + if (likesRepository.existsByMemberIdAndSpotId(member.getId(), spotId)) { + throw new AlreadyLikesException(); + } + + Likes likes = Likes.builder() + .member(member) + .spot(spot) + .build(); + + likesRepository.save(likes); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.")) + .build(); + + return ResponseEntity.ok(apiResponse); + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java index bb7b91a1..0171c7fa 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java @@ -1,15 +1,36 @@ package com.ttubeog.domain.likes.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "likes") public class Likes extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne + @JoinColumn(name = "member_id") + private Member member; + + @ManyToOne + @JoinColumn(name = "store_id") + private Store store; + + @ManyToOne + @JoinColumn(name = "spot_id") + private Spot spot; } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index b0794425..60711a65 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -6,4 +6,7 @@ @Repository public interface LikesRepository extends JpaRepository { + + boolean existsByMemberIdAndStoreId(Long memberId, Long StoreId); + boolean existsByMemberIdAndSpotId(Long memberId, Long spotId); } diff --git a/src/main/java/com/ttubeog/domain/likes/exception/AlreadyLikesException.java b/src/main/java/com/ttubeog/domain/likes/exception/AlreadyLikesException.java new file mode 100644 index 00000000..179d8b39 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/likes/exception/AlreadyLikesException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.likes.exception; + +public class AlreadyLikesException extends RuntimeException { + + public AlreadyLikesException() { + super("이미 좋아요를 눌렀습니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/exception/NonExistentSpotException.java b/src/main/java/com/ttubeog/domain/spot/exception/NonExistentSpotException.java new file mode 100644 index 00000000..e2b93976 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/exception/NonExistentSpotException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.spot.exception; + +public class NonExistentSpotException extends RuntimeException { + + public NonExistentSpotException() { + super("존재하지 않는 산책스팟입니다."); + } +} From 474d8fa1184b9ee941523906be929eb6f5f7fb47 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 02:43:13 +0900 Subject: [PATCH 121/356] =?UTF-8?q?[Feat]=20=EC=82=B0=EC=B1=85=EC=8A=A4?= =?UTF-8?q?=ED=8C=9F=20createSpot,=20findBySpotId=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/area/domain/DongArea.java | 2 + .../image/application/ImageService.java | 4 + .../ttubeog/domain/image/domain/Image.java | 15 +-- .../domain/repository/ImageRepository.java | 4 +- .../domain/spot/application/SpotService.java | 107 ++++++++++++++---- .../com/ttubeog/domain/spot/domain/Spot.java | 17 +-- .../domain/repository/SpotRepository.java | 7 ++ .../dto/request/CreateSpotRequestDto.java | 2 - .../dto/response/CreateSpotResponseDto.java | 26 +++++ .../exception/InvalidDongAreaException.java | 8 ++ .../InvalidImageListSizeException.java | 8 ++ .../exception/InvalidSpotIdException.java | 8 ++ 12 files changed, 169 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/image/application/ImageService.java create mode 100644 src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java create mode 100644 src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java create mode 100644 src/main/java/com/ttubeog/domain/spot/exception/InvalidImageListSizeException.java create mode 100644 src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java index b407a2cc..5054c28e 100644 --- a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java +++ b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java @@ -5,7 +5,9 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.Getter; +@Getter @Entity public class DongArea extends BaseEntity { diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java new file mode 100644 index 00000000..21ab9b3b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.image.application; + +public class ImageService { +} diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java index f1a67f8b..f0fc1458 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/Image.java +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -7,6 +7,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.apache.ibatis.annotations.Many; @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -19,16 +20,16 @@ public class Image extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "spot_id") - private Spot spot; - - @Column(name = "image") + @Column(name = "image", nullable = false) private String image; - public Image(Long id, Spot spot, String image) { + @ManyToOne + @JoinColumn(name = "spot") + private Spot spot; + + public Image(Long id, String image, Spot spot) { this.id = id; - this.spot = spot; this.image = image; + this.spot = spot; } } diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java index 7a65d669..115e05b1 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -2,14 +2,16 @@ import com.ttubeog.domain.image.domain.Image; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface ImageRepository extends JpaRepository { @Override List findAll(); - findBySpotId(Long id); + List findBySpotId(Long id); } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index f152f7cf..b2928aa9 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -11,14 +11,21 @@ import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.domain.spot.dto.response.CreateSpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; +import com.ttubeog.domain.spot.exception.InvalidDongAreaException; +import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; +import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.ApiResponse; +import feign.Response; import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.awt.font.ImageGraphicAttribute; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -32,41 +39,99 @@ public class SpotService { private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; + private List getSpotImageString(Spot spot) { + List spotImageString = new ArrayList<>(); + + for (int i = 0; i < spot.getImages().size(); i++) { + spotImageString.add(spotImageString.size(), spot.getImages().get(i).getImage()); + } + + return spotImageString; + } + + @NotNull + private ResponseEntity getResponseEntity(Spot spot) { + CreateSpotResponseDto createSpotResponseDto = CreateSpotResponseDto.builder() + .id(spot.getId()) + .memberId(spot.getMember().getId()) + .dongAreaId(spot.getDongArea().getId()) + .detailAddress(spot.getDetailAddress()) + .name(spot.getName()) + .info(spot.getInfo()) + .latitude(spot.getLatitude()) + .longitude(spot.getLongitude()) + .image(getSpotImageString(spot)) + .stars(spot.getStars()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(createSpotResponseDto) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + @Transactional public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { + // 유효한 사용자 로그인 상태인지 체크 memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + // 중복된 이름을 가진 산책 스팟인지 체크 if (spotRepository.findByName(createSpotRequestDto.getName()).isPresent()) { throw new AlreadyExistsSpotException(); } - Optional memberOptional = memberRepository.findById(createSpotRequestDto.getMemberId()); - Optional dongAreaOptional = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()); - List imageOptional = imageRepository.findBySpotId(createSpotRequestDto.getId()); - if (memberOptional.isPresent() && dongAreaOptional.isPresent() && imageOptional.isPresent()) { - Member member = memberOptional.get(); - DongArea dongArea = dongAreaOptional.get(); - Image image = imageOptional.get(); - - Spot spot = Spot.builder() - .member(member) - .dongArea(dongArea) - .detailAddress(createSpotRequestDto.getDetailAddress()) - .name(createSpotRequestDto.getName()) - .info(createSpotRequestDto.getInfo()) - .latitude(createSpotRequestDto.getLatitude()) - .longitude(createSpotRequestDto.getLongitude()) - .images(image) + // 산책 스팟 등록 요청 유저가 유효한지 체크 + Member member = memberRepository.findById(createSpotRequestDto.getMemberId()).orElseThrow(InvalidMemberException::new); + + // 지역코드가 유효한지 체크 + DongArea dongArea = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); + + // 산책 스팟 이미지가 1~10개 사이인지 체크 + if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { + throw new InvalidImageListSizeException(); + } + + // 이미지 저장 + List imageList = new ArrayList<>(); + for (int i = 0; i < createSpotRequestDto.getImage().size(); i++) { + Image image = Image.builder() + .image(createSpotRequestDto.getImage().get(i)) .build(); + imageList.add(imageList.size(), image); + imageRepository.save(image); } + // 평점 초기화 + Float stars = createSpotRequestDto.getStars() != null ? createSpotRequestDto.getStars() : 0.0f; + Spot spot = Spot.builder() + .member(member) + .dongArea(dongArea) + .detailAddress(createSpotRequestDto.getDetailAddress()) + .name(createSpotRequestDto.getName()) + .info(createSpotRequestDto.getInfo()) + .latitude(createSpotRequestDto.getLatitude()) + .longitude(createSpotRequestDto.getLongitude()) + .images(imageList) + .stars(stars) + .build(); - return null; + spotRepository.save(spot); + + return getResponseEntity(spot); } - public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Integer spotId) { - return null; + public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Long spotId) { + + // 유효한 사용자 로그인 상태인지 체크 + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + return getResponseEntity(spot); } public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotRequestDto updateSpotRequestDto) { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 043beb4d..9efcf8b0 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -23,21 +23,22 @@ public class Spot extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(nullable = false) private Long id; - @Column(name = "name") + @Column(name = "name", nullable = false) private String name; - @Column(name = "info") + @Column(name = "info", nullable = false) private String info; - @Column(name = "latitude") + @Column(name = "latitude", nullable = false) private Float latitude; - @Column(name = "longitude") + @Column(name = "longitude", nullable = false) private Float longitude; - @Column(name = "images") + @Column(name = "images", nullable = false) @OneToMany(mappedBy = "spot", cascade = CascadeType.ALL, orphanRemoval = true) private List images; @@ -45,14 +46,14 @@ public class Spot extends BaseEntity { private Float stars; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id)") + @JoinColumn(name = "member_id", nullable = false) private Member member; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "dong_area_id") + @JoinColumn(name = "dong_area_id", nullable = false) private DongArea dongArea; - @Column(name = "detail_address") + @Column(name = "detail_address", nullable = false) private String detailAddress; public Spot(Long id, String name, String info, Float latitude, Float longitude, List images, Float stars, Member member, DongArea dongArea, String detailAddress) { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java index cf5920d5..c2022844 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java @@ -4,6 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + @Repository public interface SpotRepository extends JpaRepository { + + Optional findByName(String name); + } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 81c1515a..ce19e77d 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -3,12 +3,10 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import lombok.Setter; import java.util.List; @Getter -@Setter @Builder @AllArgsConstructor public class CreateSpotRequestDto { diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java new file mode 100644 index 00000000..c1c4967b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java @@ -0,0 +1,26 @@ +package com.ttubeog.domain.spot.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +public class CreateSpotResponseDto { + + private Long id; + private String name; + private Long memberId; + private Long dongAreaId; + private String detailAddress; + private String info; + private Float latitude; + private Float longitude; + private List image; + private Float stars; + +} diff --git a/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java b/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java new file mode 100644 index 00000000..34ec557c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.spot.exception; + +public class InvalidDongAreaException extends RuntimeException{ + + public InvalidDongAreaException() { + super("유효하지 않은 지역 정보입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/exception/InvalidImageListSizeException.java b/src/main/java/com/ttubeog/domain/spot/exception/InvalidImageListSizeException.java new file mode 100644 index 00000000..a4905d8b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/exception/InvalidImageListSizeException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.spot.exception; + +public class InvalidImageListSizeException extends RuntimeException { + + public InvalidImageListSizeException() { + super("유효하지 않은 이미지 개수입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java b/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java new file mode 100644 index 00000000..82b74f54 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.spot.exception; + +public class InvalidSpotIdException extends RuntimeException{ + + public InvalidSpotIdException() { + super("존재하지 않은 산책 스팟 Id 값입니다."); + } +} From d75f1a409258c3c47ca81cdd7984bed2589d3ad2 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:29:52 +0900 Subject: [PATCH 122/356] =?UTF-8?q?[Feat]=20updateSpot=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/spot/application/SpotService.java | 51 ++++++++++++++----- .../com/ttubeog/domain/spot/domain/Spot.java | 15 ++++++ .../dto/request/CreateSpotRequestDto.java | 2 - .../dto/request/UpdateSpotRequestDto.java | 19 +++++++ ...tResponseDto.java => SpotResponseDto.java} | 2 +- 5 files changed, 73 insertions(+), 16 deletions(-) rename src/main/java/com/ttubeog/domain/spot/dto/response/{CreateSpotResponseDto.java => SpotResponseDto.java} (92%) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index b2928aa9..9cfe158b 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -11,14 +11,13 @@ import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; -import com.ttubeog.domain.spot.dto.response.CreateSpotResponseDto; +import com.ttubeog.domain.spot.dto.response.SpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.domain.spot.exception.InvalidDongAreaException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; -import feign.Response; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; @@ -27,7 +26,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; @RequiredArgsConstructor @Service @@ -51,7 +49,7 @@ private List getSpotImageString(Spot spot) { @NotNull private ResponseEntity getResponseEntity(Spot spot) { - CreateSpotResponseDto createSpotResponseDto = CreateSpotResponseDto.builder() + SpotResponseDto createSpotResponseDto = SpotResponseDto.builder() .id(spot.getId()) .memberId(spot.getMember().getId()) .dongAreaId(spot.getDongArea().getId()) @@ -76,16 +74,13 @@ private ResponseEntity getResponseEntity(Spot spot) { public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { // 유효한 사용자 로그인 상태인지 체크 - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); // 중복된 이름을 가진 산책 스팟인지 체크 if (spotRepository.findByName(createSpotRequestDto.getName()).isPresent()) { throw new AlreadyExistsSpotException(); } - // 산책 스팟 등록 요청 유저가 유효한지 체크 - Member member = memberRepository.findById(createSpotRequestDto.getMemberId()).orElseThrow(InvalidMemberException::new); - // 지역코드가 유효한지 체크 DongArea dongArea = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); @@ -104,9 +99,6 @@ public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotReque imageRepository.save(image); } - // 평점 초기화 - Float stars = createSpotRequestDto.getStars() != null ? createSpotRequestDto.getStars() : 0.0f; - Spot spot = Spot.builder() .member(member) .dongArea(dongArea) @@ -116,7 +108,7 @@ public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotReque .latitude(createSpotRequestDto.getLatitude()) .longitude(createSpotRequestDto.getLongitude()) .images(imageList) - .stars(stars) + .stars(0.0f) .build(); spotRepository.save(spot); @@ -135,7 +127,40 @@ public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Long spotId) } public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotRequestDto updateSpotRequestDto) { - return null; + + // 유효한 사용자 로그인 상태인지 체크 + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Spot spot = spotRepository.findById(updateSpotRequestDto.getId()).orElseThrow(InvalidSpotIdException::new); + + // 중복된 이름을 가진 산책 스팟인지 체크 + if (spotRepository.findByName(updateSpotRequestDto.getName()).isPresent()) { + throw new AlreadyExistsSpotException(); + } + + // 지역코드가 유효한지 체크 + DongArea dongArea = dongAreaRepository.findById(updateSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); + + // 산책 스팟 이미지가 1~10개 사이인지 체크 + if (updateSpotRequestDto.getImage().isEmpty() || updateSpotRequestDto.getImage().size() > 10) { + throw new InvalidImageListSizeException(); + } + + // 이미지 저장 + List imageList = new ArrayList<>(); + for (int i = 0; i < updateSpotRequestDto.getImage().size(); i++) { + Image image = Image.builder() + .image(updateSpotRequestDto.getImage().get(i)) + .build(); + imageList.add(imageList.size(), image); + imageRepository.save(image); + } + + spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), imageList, dongArea, updateSpotRequestDto.getDetailAddress()); + + spotRepository.save(spot); + + return getResponseEntity(spot); } public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Integer spotId) { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 9efcf8b0..3b40909f 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -68,4 +68,19 @@ public Spot(Long id, String name, String info, Float latitude, Float longitude, this.dongArea = dongArea; this.detailAddress = detailAddress; } + + public void updateSpot(String name, String info, Float latitude, Float longitude, List images, DongArea dongArea, String detailAddress) { + this.name = name; + this.info = info; + this.latitude = latitude; + this.longitude = longitude; + this.images = images; + this.dongArea = dongArea; + this.detailAddress = detailAddress; + } + + public void updateStars(Float stars) { + this.stars = stars; + } + } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index ce19e77d..ea8d1762 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -13,13 +13,11 @@ public class CreateSpotRequestDto { private Long id; private String name; - private Long memberId; private Long dongAreaId; private String detailAddress; private String info; private Float latitude; private Float longitude; private List image; - private Float stars; } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index e31fa431..0a8db6b8 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -1,4 +1,23 @@ package com.ttubeog.domain.spot.dto.request; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor public class UpdateSpotRequestDto { + + private Long id; + private String name; + private Long dongAreaId; + private String detailAddress; + private String info; + private Float latitude; + private Float longitude; + private List image; + } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java similarity index 92% rename from src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java rename to src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index c1c4967b..e7770b12 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/CreateSpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -10,7 +10,7 @@ @Getter @Builder @AllArgsConstructor -public class CreateSpotResponseDto { +public class SpotResponseDto { private Long id; private String name; From eed4365ea94954061616265a9f4404cad95b0d31 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:36:49 +0900 Subject: [PATCH 123/356] [Feat] deleteSpot API implement --- .../domain/spot/application/SpotService.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 9cfe158b..544f9aa6 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.spot.application; +import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.image.domain.Image; @@ -18,6 +19,7 @@ import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; @@ -126,22 +128,24 @@ public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Long spotId) return getResponseEntity(spot); } + @Transactional public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotRequestDto updateSpotRequestDto) { // 유효한 사용자 로그인 상태인지 체크 memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + // 존재하는 산책 스팟을 수정하려는지 체크 Spot spot = spotRepository.findById(updateSpotRequestDto.getId()).orElseThrow(InvalidSpotIdException::new); - // 중복된 이름을 가진 산책 스팟인지 체크 + // 수정하려는 이름과 중복된 이름을 가진 산책 스팟이 있는지 if (spotRepository.findByName(updateSpotRequestDto.getName()).isPresent()) { throw new AlreadyExistsSpotException(); } - // 지역코드가 유효한지 체크 + // 수정하려는 지역코드가 유효한지 체크 DongArea dongArea = dongAreaRepository.findById(updateSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); - // 산책 스팟 이미지가 1~10개 사이인지 체크 + // 수정하려는 산책 스팟 이미지가 1~10개 사이인지 체크 if (updateSpotRequestDto.getImage().isEmpty() || updateSpotRequestDto.getImage().size() > 10) { throw new InvalidImageListSizeException(); } @@ -163,10 +167,25 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque return getResponseEntity(spot); } - public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Integer spotId) { - return null; + @Transactional + public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { + + // 유효한 사용자 로그인 상태인지 체크 + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + spotRepository.delete(spot); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("산책 스팟을 삭제햇습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); } + @Transactional public ResponseEntity likeSpot(UserPrincipal userPrincipal, Integer spotId) { return null; } From 36e9a0571b40ee72dcac870bb1a3c79645e98306 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:43:47 +0900 Subject: [PATCH 124/356] [Feat] deleteSpot API implement --- .../domain/image/exception/InvalidImageException.java | 8 ++++++++ .../com/ttubeog/domain/spot/application/SpotService.java | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java diff --git a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java new file mode 100644 index 00000000..4c50a271 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.image.exception; + +public class InvalidImageException extends RuntimeException { + + public InvalidImageException() { + super("유효하지 않은 이미지입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 544f9aa6..cc6477f3 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -175,6 +176,11 @@ public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + List imageList = spot.getImages(); + for (Image image : imageList) { + imageRepository.delete(imageRepository.findById(image.getId()).orElseThrow(InvalidImageException::new)); + } + spotRepository.delete(spot); ApiResponse apiResponse = ApiResponse.builder() From 6488380f3ff8257e1446ed039cc84ce3dff2c8d4 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:49:15 +0900 Subject: [PATCH 125/356] =?UTF-8?q?[Feat]=20spotController=20request=20?= =?UTF-8?q?=EC=88=98=EB=A0=B9=20=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GuestBookService.java | 5 ++ .../domain/spot/application/SpotService.java | 1 - .../spot/presentation/SpotController.java | 77 ++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index c45df13d..a6e0f71e 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.guestbook.application; +import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +11,6 @@ @Service @Transactional(readOnly = true) public class GuestBookService { + public ResponseEntity createGuestBook(UserPrincipal userPrincipal, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { + } } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index cc6477f3..af2dfa6f 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.spot.application; -import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.image.domain.Image; diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index bf704cd4..0b6392e4 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -1,7 +1,82 @@ package com.ttubeog.domain.spot.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.guestbook.application.GuestBookService; +import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.domain.spot.application.SpotService; +import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; +import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Spot", description = "Spot API(산책 스팟 API)") @RestController +@RequiredArgsConstructor +@RequestMapping("api/v1/spot") public class SpotController { + + private final SpotService spotService; + private final GuestBookService guestBookService; + + @Operation(summary = "산책 스팟 생성", description = "산책 스팟을 생성합니다.") + @PostMapping + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestBody CreateSpotRequestDto createSpotRequestDto + ) throws JsonProcessingException { + return spotService.createSpot(userPrincipal, createSpotRequestDto); + } + + @Operation(summary = "산책 스팟 세부 사항 조회", description = "산책 스팟의 세부 사항을 조회합니다.") + @GetMapping("/{spotId}") + public ResponseEntity findBySpotId( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Long spotId + ) throws JsonProcessingException { + return spotService.findBySpotId(userPrincipal, spotId); + } + + @Operation(summary = "산책 스팟 수정", description = "산책 스팟에 대한 정보를 수정합니다.") + @PatchMapping + public ResponseEntity updateSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestBody UpdateSpotRequestDto updateSpotRequestDto + ) throws JsonProcessingException { + return spotService.updateSpot(userPrincipal, updateSpotRequestDto); + } + + @Operation(summary = "산책 스팟 삭제", description = "산책 스팟을 삭제합니다.") + @DeleteMapping("/{spotId}") + public ResponseEntity deleteSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Long spotId + ) throws JsonProcessingException { + return spotService.deleteSpot(userPrincipal, spotId); + } + + @Operation(summary = "산책 스팟 방명록 작성", description = "산책 스팟에 종속된 방명록을 작성합니다.") + @PostMapping("/{spotId}/guestbook") + public ResponseEntity createGuestBook( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId, + @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto + ) throws JsonProcessingException { + return guestBookService.createGuestBook(userPrincipal, spotId, createGuestBookRequestDto); + } + + @Operation(summary = "산책 스팟 좋아요 누르기", description = "산책 스팟에 좋아요를 누릅니다.") + @PatchMapping("/{spotId}/likes") + public ResponseEntity likeSpot( + @CurrentUser UserPrincipal userPrincipal, + @RequestParam(name = "spotId") Integer spotId + ) throws JsonProcessingException { + return spotService.likeSpot(userPrincipal, spotId); + } } From 37c8a9b6613cd4beda93862e69d04394c574f9be Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:49:46 +0900 Subject: [PATCH 126/356] =?UTF-8?q?[Feat]=20guestbookservice=20=EC=B4=88?= =?UTF-8?q?=EC=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/guestbook/application/GuestBookService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index a6e0f71e..d8c1c7b3 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -12,5 +12,6 @@ @Transactional(readOnly = true) public class GuestBookService { public ResponseEntity createGuestBook(UserPrincipal userPrincipal, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { + return null; } } From 72791c6c6418dee46e2549087d81733f91ea8596 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 05:52:07 +0900 Subject: [PATCH 127/356] =?UTF-8?q?[Feat]=20createImage=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/application/ImageService.java | 66 +++++++++++++++++++ .../ttubeog/domain/image/domain/Image.java | 10 ++- .../image/dto/request/ImageRequestDto.java | 16 +++++ .../image/dto/request/ImageRequestType.java | 6 ++ .../image/dto/response/ImageResponseDto.java | 17 +++++ .../domain/spot/application/SpotService.java | 47 ++++++------- .../com/ttubeog/domain/spot/domain/Spot.java | 10 +-- .../dto/request/CreateSpotRequestDto.java | 1 - .../spot/dto/response/SpotResponseDto.java | 7 ++ .../ttubeog/domain/store/domain/Store.java | 3 + 10 files changed, 149 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java create mode 100644 src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index 21ab9b3b..21ceafb2 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -1,4 +1,70 @@ package com.ttubeog.domain.image.application; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.image.dto.request.ImageRequestDto; +import com.ttubeog.domain.image.dto.response.ImageResponseDto; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +import static com.ttubeog.domain.image.dto.request.ImageRequestType.SPOT; + +@RequiredArgsConstructor +@Service +@Transactional(readOnly = true) public class ImageService { + + private final ImageRepository imageRepository; + private final SpotRepository spotRepository; + private final StoreRepository storeRepository; + + public static List getImageString(List imageList) { + List imageString = new ArrayList<>(); + + for (Image image : imageList) { + imageString.add(imageString.size(), image.getImage()); + } + + return imageString; + } + + @Transactional + public ImageResponseDto createImage(ImageRequestDto imageRequestDto) { + Image image; + ImageResponseDto imageResponseDto; + if (imageRequestDto.imageRequestType == SPOT) { + image = Image.builder() + .image(imageRequestDto.getImage()) + .spot(spotRepository.findById(imageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .build(); + + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .placeId(image.getSpot().getId()) + .build(); + } else { + image = Image.builder() + .image(imageRequestDto.getImage()) + .store(storeRepository.findById(imageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .build(); + + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .placeId(image.getStore().getId()) + .build(); + } + imageRepository.save(image); + + return imageResponseDto; + } + } diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java index f0fc1458..18938788 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/Image.java +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -23,13 +24,18 @@ public class Image extends BaseEntity { @Column(name = "image", nullable = false) private String image; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "spot") private Spot spot; - public Image(Long id, String image, Spot spot) { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store") + private Store store; + + public Image(Long id, String image, Spot spot, Store store) { this.id = id; this.image = image; this.spot = spot; + this.store = store; } } diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java new file mode 100644 index 00000000..60cb98bf --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java @@ -0,0 +1,16 @@ +package com.ttubeog.domain.image.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class ImageRequestDto { + + public String image; + public ImageRequestType imageRequestType; + public Long placeId; + +} diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java b/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java new file mode 100644 index 00000000..dff49fa5 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java @@ -0,0 +1,6 @@ +package com.ttubeog.domain.image.dto.request; + +public enum ImageRequestType { + SPOT, + STORE +} diff --git a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java new file mode 100644 index 00000000..8570034c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java @@ -0,0 +1,17 @@ +package com.ttubeog.domain.image.dto.response; + +import com.ttubeog.domain.image.dto.request.ImageRequestType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class ImageResponseDto { + + public Long id; + public String image; + public Long placeId; + +} diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index af2dfa6f..14bc9bb2 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -2,8 +2,11 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; +import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.image.dto.request.ImageRequestDto; +import com.ttubeog.domain.image.dto.request.ImageRequestType; import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -20,6 +23,8 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import lombok.AllArgsConstructor; +import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; @@ -29,6 +34,8 @@ import java.util.ArrayList; import java.util.List; +import static com.ttubeog.domain.image.application.ImageService.getImageString; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -39,18 +46,11 @@ public class SpotService { private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; - private List getSpotImageString(Spot spot) { - List spotImageString = new ArrayList<>(); - - for (int i = 0; i < spot.getImages().size(); i++) { - spotImageString.add(spotImageString.size(), spot.getImages().get(i).getImage()); - } - - return spotImageString; - } + private final ImageService imageService; - @NotNull + @NonNull private ResponseEntity getResponseEntity(Spot spot) { + SpotResponseDto createSpotResponseDto = SpotResponseDto.builder() .id(spot.getId()) .memberId(spot.getMember().getId()) @@ -60,7 +60,7 @@ private ResponseEntity getResponseEntity(Spot spot) { .info(spot.getInfo()) .latitude(spot.getLatitude()) .longitude(spot.getLongitude()) - .image(getSpotImageString(spot)) + .image(getImageString(imageRepository.findBySpotId(spot.getId()))) .stars(spot.getStars()) .build(); @@ -90,17 +90,8 @@ public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotReque if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { throw new InvalidImageListSizeException(); } - - // 이미지 저장 - List imageList = new ArrayList<>(); - for (int i = 0; i < createSpotRequestDto.getImage().size(); i++) { - Image image = Image.builder() - .image(createSpotRequestDto.getImage().get(i)) - .build(); - imageList.add(imageList.size(), image); - imageRepository.save(image); - } - + + // 산책 스팟 저장 Spot spot = Spot.builder() .member(member) .dongArea(dongArea) @@ -109,12 +100,22 @@ public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotReque .info(createSpotRequestDto.getInfo()) .latitude(createSpotRequestDto.getLatitude()) .longitude(createSpotRequestDto.getLongitude()) - .images(imageList) .stars(0.0f) .build(); spotRepository.save(spot); + // 이미지 저장 + List imageList = createSpotRequestDto.getImage(); + for (String s : imageList) { + ImageRequestDto imageRequestDto = ImageRequestDto.builder() + .image(s) + .imageRequestType(ImageRequestType.SPOT) + .placeId(spot.getId()) + .build(); + imageService.createImage(imageRequestDto); + } + return getResponseEntity(spot); } diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 3b40909f..fa7430e7 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -38,10 +38,6 @@ public class Spot extends BaseEntity { @Column(name = "longitude", nullable = false) private Float longitude; - @Column(name = "images", nullable = false) - @OneToMany(mappedBy = "spot", cascade = CascadeType.ALL, orphanRemoval = true) - private List images; - @Column(name = "starts") private Float stars; @@ -56,25 +52,23 @@ public class Spot extends BaseEntity { @Column(name = "detail_address", nullable = false) private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, List images, Float stars, Member member, DongArea dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, DongArea dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; this.latitude = latitude; this.longitude = longitude; - this.images = images; this.stars = stars; this.member = member; this.dongArea = dongArea; this.detailAddress = detailAddress; } - public void updateSpot(String name, String info, Float latitude, Float longitude, List images, DongArea dongArea, String detailAddress) { + public void updateSpot(String name, String info, Float latitude, Float longitude, DongArea dongArea, String detailAddress) { this.name = name; this.info = info; this.latitude = latitude; this.longitude = longitude; - this.images = images; this.dongArea = dongArea; this.detailAddress = detailAddress; } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index ea8d1762..94354f68 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -11,7 +11,6 @@ @AllArgsConstructor public class CreateSpotRequestDto { - private Long id; private String name; private Long dongAreaId; private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index e7770b12..f4b0629e 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -1,12 +1,19 @@ package com.ttubeog.domain.spot.dto.response; +import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.global.payload.ApiResponse; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NonNull; +import org.springframework.http.ResponseEntity; import java.util.List; +import static com.ttubeog.domain.image.application.ImageService.getImageString; + @Getter @Builder @AllArgsConstructor diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 8dcbe437..d143bd6e 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -5,11 +5,14 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.Getter; +@Getter @Entity public class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + } From 68f661d01fa6787c892506d403736a9e5686a02e Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 06:06:15 +0900 Subject: [PATCH 128/356] =?UTF-8?q?[Feat]=20updateImage=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/application/ImageService.java | 41 +++++++++++++++---- .../ttubeog/domain/image/domain/Image.java | 10 +++++ ...estDto.java => CreateImageRequestDto.java} | 2 +- .../dto/request/UpdateImageRequestDto.java | 16 ++++++++ .../domain/spot/application/SpotService.java | 29 +++++++------ 5 files changed, 73 insertions(+), 25 deletions(-) rename src/main/java/com/ttubeog/domain/image/dto/request/{ImageRequestDto.java => CreateImageRequestDto.java} (87%) create mode 100644 src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index 21ceafb2..b383c67b 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -2,13 +2,13 @@ import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.ImageRequestDto; +import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; +import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; import com.ttubeog.domain.image.dto.response.ImageResponseDto; -import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,13 +38,13 @@ public static List getImageString(List imageList) { } @Transactional - public ImageResponseDto createImage(ImageRequestDto imageRequestDto) { + public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) { Image image; ImageResponseDto imageResponseDto; - if (imageRequestDto.imageRequestType == SPOT) { + if (createImageRequestDto.imageRequestType == SPOT) { image = Image.builder() - .image(imageRequestDto.getImage()) - .spot(spotRepository.findById(imageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .image(createImageRequestDto.getImage()) + .spot(spotRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() @@ -53,8 +53,8 @@ public ImageResponseDto createImage(ImageRequestDto imageRequestDto) { .build(); } else { image = Image.builder() - .image(imageRequestDto.getImage()) - .store(storeRepository.findById(imageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .image(createImageRequestDto.getImage()) + .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() @@ -67,4 +67,27 @@ public ImageResponseDto createImage(ImageRequestDto imageRequestDto) { return imageResponseDto; } + @Transactional + public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) { + Image image = imageRepository.findById(updateImageRequestDto.getId()).orElseThrow(InvalidImageException::new); + ImageResponseDto imageResponseDto; + + if (updateImageRequestDto.imageRequestType == SPOT) { + image.updateImage(updateImageRequestDto.getImage(), spotRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .placeId(image.getSpot().getId()) + .build(); + } else { + image.updateImage(updateImageRequestDto.getImage(), storeRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .placeId(image.getStore().getId()) + .build(); + } + + imageRepository.save(image); + + return imageResponseDto; + } } diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java index 18938788..4bf92064 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/Image.java +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -38,4 +38,14 @@ public Image(Long id, String image, Spot spot, Store store) { this.spot = spot; this.store = store; } + + public void updateImage(String image, Spot spot) { + this.image = image; + this.spot = spot; + } + + public void updateImage(String image, Store store) { + this.image = image; + this.store = store; + } } diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java similarity index 87% rename from src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java rename to src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java index 60cb98bf..7964aff5 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java @@ -7,7 +7,7 @@ @Getter @Builder @AllArgsConstructor -public class ImageRequestDto { +public class CreateImageRequestDto { public String image; public ImageRequestType imageRequestType; diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java new file mode 100644 index 00000000..795ed37d --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java @@ -0,0 +1,16 @@ +package com.ttubeog.domain.image.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class UpdateImageRequestDto { + + public Long id; + public String image; + public ImageRequestType imageRequestType; + public Long placeId; +} diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 14bc9bb2..d9027a98 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -5,7 +5,7 @@ import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.ImageRequestDto; +import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.image.dto.request.ImageRequestType; import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; @@ -23,10 +23,8 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; -import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -108,12 +106,12 @@ public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotReque // 이미지 저장 List imageList = createSpotRequestDto.getImage(); for (String s : imageList) { - ImageRequestDto imageRequestDto = ImageRequestDto.builder() + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(s) .imageRequestType(ImageRequestType.SPOT) .placeId(spot.getId()) .build(); - imageService.createImage(imageRequestDto); + imageService.createImage(createImageRequestDto); } return getResponseEntity(spot); @@ -151,20 +149,21 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque throw new InvalidImageListSizeException(); } - // 이미지 저장 - List imageList = new ArrayList<>(); - for (int i = 0; i < updateSpotRequestDto.getImage().size(); i++) { - Image image = Image.builder() - .image(updateSpotRequestDto.getImage().get(i)) - .build(); - imageList.add(imageList.size(), image); - imageRepository.save(image); - } - spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), imageList, dongArea, updateSpotRequestDto.getDetailAddress()); spotRepository.save(spot); + // 이미지 저장 + List imageList = updateSpotRequestDto.getImage(); + for (String s : imageList) { + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + .image(s) + .imageRequestType(ImageRequestType.SPOT) + .placeId(spot.getId()) + .build(); + imageService.createImage(createImageRequestDto); + } + return getResponseEntity(spot); } From 12909adaec5ef5cdf51d035ebc2bd589a3aa3ecf Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 06:14:31 +0900 Subject: [PATCH 129/356] =?UTF-8?q?[Feat]=20deleteImage=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/image/application/ImageService.java | 11 +++++++++++ .../image/domain/repository/ImageRepository.java | 2 ++ .../domain/spot/application/SpotService.java | 13 +++++++------ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index b383c67b..a535c44c 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -10,6 +10,7 @@ import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.repository.StoreRepository; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.parameters.P; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -39,6 +40,7 @@ public static List getImageString(List imageList) { @Transactional public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) { + Image image; ImageResponseDto imageResponseDto; if (createImageRequestDto.imageRequestType == SPOT) { @@ -69,6 +71,7 @@ public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) @Transactional public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) { + Image image = imageRepository.findById(updateImageRequestDto.getId()).orElseThrow(InvalidImageException::new); ImageResponseDto imageResponseDto; @@ -90,4 +93,12 @@ public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) return imageResponseDto; } + + @Transactional + public void deleteImage(Long imageId) { + + Image image = imageRepository.findById(imageId).orElseThrow(InvalidImageException::new); + imageRepository.delete(image); + + } } diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java index 115e05b1..61c4a10d 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -14,4 +14,6 @@ public interface ImageRepository extends JpaRepository { List findAll(); List findBySpotId(Long id); + + List findByStoreId(Long id); } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index d9027a98..111f4b1b 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.image.dto.request.ImageRequestType; +import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -156,12 +157,12 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque // 이미지 저장 List imageList = updateSpotRequestDto.getImage(); for (String s : imageList) { - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + UpdateImageRequestDto updateImageRequestDto = UpdateImageRequestDto.builder() .image(s) .imageRequestType(ImageRequestType.SPOT) .placeId(spot.getId()) .build(); - imageService.createImage(createImageRequestDto); + imageService.updateImage(updateImageRequestDto); } return getResponseEntity(spot); @@ -175,13 +176,13 @@ public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); - List imageList = spot.getImages(); + spotRepository.delete(spot); + + List imageList = imageRepository.findBySpotId(spot.getId()); for (Image image : imageList) { - imageRepository.delete(imageRepository.findById(image.getId()).orElseThrow(InvalidImageException::new)); + imageService.deleteImage(image.getId()); } - spotRepository.delete(spot); - ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("산책 스팟을 삭제햇습니다.").build()) From 036253a3b6925be47c079136bdbe525aaeaf1359 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 06:15:24 +0900 Subject: [PATCH 130/356] =?UTF-8?q?[Feat]=20deleteImage=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 111f4b1b..f4da400f 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -150,7 +150,7 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque throw new InvalidImageListSizeException(); } - spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), imageList, dongArea, updateSpotRequestDto.getDetailAddress()); + spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), dongArea, updateSpotRequestDto.getDetailAddress()); spotRepository.save(spot); From f6e3a9b36b8425092a89676764b4b9dd66a9f33b Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 06:16:51 +0900 Subject: [PATCH 131/356] =?UTF-8?q?[Refac]=20spot=20service=20=EB=A6=AC?= =?UTF-8?q?=ED=8E=99=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index f4da400f..9c335b1e 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -8,7 +8,6 @@ import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.image.dto.request.ImageRequestType; import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; -import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -30,7 +29,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; import static com.ttubeog.domain.image.application.ImageService.getImageString; @@ -172,7 +170,7 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { // 유효한 사용자 로그인 상태인지 체크 - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); From a0ed3859f1f9457cba253a88c458103e4f5318b9 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:30:59 +0900 Subject: [PATCH 132/356] Update gradle.yml to start redis-server --- .github/workflows/gradle.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 71cbf5b8..bb7344db 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -108,6 +108,15 @@ jobs: source: . target: "/home/ubuntu/app/code" + - name: Start redis-server + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY }} + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USER }} + script: | + sudo systemctl start redis-server + deploy: name: CD with SSH From fe6e46529ba3138e3fc2368695fded8579861763 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:39:33 +0900 Subject: [PATCH 133/356] Update gradle.yml --- .github/workflows/gradle.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index bb7344db..01bcca4a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -94,9 +94,8 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} - # 기존 실행 중인 서버 종료 후 jar 파일 실행 - script: | - sudo rm -rf /home/ubuntu/app/code + command: sudo rm -rf /home/ubuntu/app/code + port: 22 - name: Upload raw sorce to EC2 @@ -114,8 +113,8 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} - script: | - sudo systemctl start redis-server + command: sudo systemctl start redis-server + port: 22 deploy: From 971e07d598099ff1fca799b5576c7a0142bd413a Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:43:51 +0900 Subject: [PATCH 134/356] Update gradle.yml --- .github/workflows/gradle.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 01bcca4a..eef5f58f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -113,8 +113,22 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} + target: /path/on/remote/server # specify the target path if needed + source: . # specify the source directory or file if needed command: sudo systemctl start redis-server port: 22 + timeout: 30s + command_timeout: 10m + use_insecure_cipher: false + rm: false + debug: false + strip_components: 0 + overwrite: false + tar_dereference: false + tar_exec: tar + proxy_port: 22 + proxy_timeout: 30s + proxy_use_insecure_cipher: false deploy: From 9ae667dc517b54dcd4d7535fa3bf1ec2ffd6e5ae Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:47:10 +0900 Subject: [PATCH 135/356] Update gradle.yml --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index eef5f58f..fe3ec596 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -113,7 +113,7 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} - target: /path/on/remote/server # specify the target path if needed + target: /home/ubuntu # specify the target path if needed source: . # specify the source directory or file if needed command: sudo systemctl start redis-server port: 22 From 36b116fa0dd84a549e7f587fd89e44cd0fdcef7b Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 2 Feb 2024 13:23:17 +0900 Subject: [PATCH 136/356] Update gradle.yml --- .github/workflows/gradle.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index fe3ec596..f4a04caf 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -119,16 +119,9 @@ jobs: port: 22 timeout: 30s command_timeout: 10m - use_insecure_cipher: false - rm: false - debug: false - strip_components: 0 - overwrite: false - tar_dereference: false tar_exec: tar proxy_port: 22 proxy_timeout: 30s - proxy_use_insecure_cipher: false deploy: From 10ba103ed8d8ef9585f30cba3361e34fb818f38f Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 2 Feb 2024 14:37:31 +0900 Subject: [PATCH 137/356] =?UTF-8?q?[Feat]=20=EB=A9=A4=EB=B2=84=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=ED=99=95=EC=9D=B8=20controller=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/AuthService.java | 25 +++++++++++-------- .../member/application/MemberService.java | 5 ++++ .../domain/repository/MemberRepository.java | 4 +++ .../member/presentation/MemberController.java | 23 +++++++++-------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 6472462f..ea00b97c 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -58,7 +58,6 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { if (memberData.isEmpty()) { member = Member.builder() .memberNumber(String.valueOf(memberInfo.getId())) - .status(Status.ACTIVE) .build(); memberRepository.save(member); @@ -67,17 +66,23 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); String refreshToken = jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); - - KakaoTokenResponse oAuthTokenResponse = KakaoTokenResponse.builder() - .accessToken(jwtTokenProvider.createAccessToken( - memberLoginData.get().getId())) - .refreshToken(refreshToken) - .isRegistered(false) - .build(); - redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); - return oAuthTokenResponse; + if (memberData.isEmpty()) { + return KakaoTokenResponse.builder() + .accessToken(jwtTokenProvider.createAccessToken( + memberLoginData.get().getId())) + .refreshToken(refreshToken) + .isRegistered(false) + .build(); + } else { + return KakaoTokenResponse.builder() + .accessToken(jwtTokenProvider.createAccessToken( + memberLoginData.get().getId())) + .refreshToken(refreshToken) + .isRegistered(true) + .build(); + } } private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String email, String platformId) { diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index edad7ab3..1283865f 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -9,6 +9,9 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,6 +46,8 @@ public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ return ResponseEntity.ok(apiResponse); } + + public MemberDto findById(Long id) { return memberMapper.findById(id); } diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 00ee161f..81b3a920 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; import io.lettuce.core.dynamic.annotation.Param; +import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -13,6 +14,9 @@ @Repository public interface MemberRepository extends JpaRepository{ + @NotNull + Optional findById(@NotNull Long userId); + Optional findByEmail(String email); Optional findByMemberNumber(String memberNumber); diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 256ce0fa..5856d0ee 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -2,8 +2,8 @@ import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.exception.NotFoundMemberException; -import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -20,29 +20,30 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Optional; + @Tag(name = "Member", description = "Member API") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/member") public class MemberController { - private final MemberService memberService; + private final MemberRepository memberRepository; @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("") - public MemberDto getCurrentMember( + public Optional getCurrentMember( @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal ) { final long memberId = SecurityUtil.getCurrentMemeberId(); - MemberDto userDto = memberService.findById(memberId); - if(userDto == null) { + Optional member = memberRepository.findById(memberId); + if (member == null) { throw new NotFoundMemberException(); } - return userDto; } - - + return member; + } } From 0c5b370dedad604d349579771741be4f253bd2cf Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 2 Feb 2024 17:06:31 +0900 Subject: [PATCH 138/356] =?UTF-8?q?[Feat]=20=ED=98=84=EC=9E=AC=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=A1=B0=ED=9A=8C=20=EC=84=B1=EA=B3=B5=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 1 - .../domain/auth/config/SecurityUtil.java | 12 +++++------ .../auth/security/JwtTokenProvider.java | 9 +++++++- .../domain/auth/service/AuthService.java | 3 ++- .../benefit/application/BenefitService.java | 9 ++++---- .../presentation/BenefitController.java | 4 ++-- .../member/application/MemberService.java | 20 ++++++++---------- .../ttubeog/domain/member/domain/Member.java | 14 ++----------- .../domain/member/domain/MemberRole.java | 19 ----------------- .../domain/member/domain/Provider.java | 6 ------ .../member/dto/response/MemberDetailRes.java | 1 - .../member/presentation/MemberController.java | 19 ++++++++--------- .../config/security/token/UserPrincipal.java | 21 +++++++------------ 13 files changed, 50 insertions(+), 88 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/member/domain/MemberRole.java delete mode 100644 src/main/java/com/ttubeog/domain/member/domain/Provider.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 451ec7de..715cc6ba 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.auth.config; -import com.ttubeog.domain.member.domain.MemberRole; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java index c8bf6033..bb7c0c34 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java @@ -12,15 +12,15 @@ private SecurityUtil() {} public static long getCurrentMemeberId() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null) { + if (authentication == null || !authentication.isAuthenticated()) { + return 1; } - long memberId = 0; - - if (authentication.getPrincipal() instanceof Member member) { - memberId = member.getId(); + if (authentication.getPrincipal() instanceof UserPrincipal) { + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); + return userPrincipal.getId(); } else { + return 10; } - return memberId; } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index 2b792796..d8c34014 100644 --- a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -73,7 +73,7 @@ private boolean isExpiredAccessToken (String token) { } public String resolveToken(HttpServletRequest request) { - String tokenHeader = request.getHeader("Authentication"); + String tokenHeader = request.getHeader("Authorization"); if (tokenHeader != null && tokenHeader.startsWith("Bearer ")) { return tokenHeader.substring(7); @@ -91,4 +91,11 @@ public String getPayload(String token) { throw new InvalidAccessTokenException(); } } + + public Long getMemberId(HttpServletRequest request) { + String token = resolveToken(request); // 클라이언트의 토큰을 가져옴 + String userId = getPayload(token); // 토큰에서 사용자 ID를 추출 + + return Long.valueOf(userId); // 사용자 ID를 Long으로 변환하여 반환 + } } diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index ea00b97c..2764b9a2 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -15,6 +15,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.RedisTemplate; @@ -102,7 +103,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String return new OAuthTokenResponse(accessToken, refreshToken, true); }) .orElseGet(() -> { - Member oauthMember = new Member(email, platform, Status.ACTIVE); + Member oauthMember = new Member(email, platform, Status.ACTIVE, ""); Member savedMember = memberRepository.save(oauthMember); String accessToken = issueAccessToken(savedMember); String refreshToken = issueRefreshToken(); diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 69c9f6e0..5f1e2c42 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.benefit.application; import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; @@ -17,9 +18,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; @@ -203,9 +202,9 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findMyBenefit(Integer page) throws JsonProcessingException { + final long memberId = SecurityUtil.getCurrentMemeberId(); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Page memberBenefitPage = memberBenefitRepository.findAllByMember(member, PageRequest.of(page, 10)); diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 84ca8ab8..91411e87 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; @@ -116,9 +117,8 @@ public ResponseEntity useBenefit( @GetMapping public ResponseEntity findMyBenefit( @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { - return benefitService.findMyBenefit(userPrincipal, page); + return benefitService.findMyBenefit(page); } } diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 1283865f..d350fc53 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,5 +1,7 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.member.dto.MemberDto; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.domain.member.domain.Member; @@ -8,6 +10,7 @@ import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.Query; @@ -23,11 +26,14 @@ @Transactional(readOnly = true) public class MemberService { private final MemberRepository memberRepository; - private final MemberMapper memberMapper; + private final JwtTokenProvider jwtTokenProvider; + // 현재 유저 조회 - public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ - Optional checkUser = memberRepository.findById(userPrincipal.getId()); + public ResponseEntity getCurrentUser(HttpServletRequest request){ + Long memberId = jwtTokenProvider.getMemberId(request); + + Optional checkUser = memberRepository.findById(memberId); DefaultAssert.isOptionalPresent(checkUser); Member member = checkUser.get(); @@ -35,7 +41,6 @@ public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ .id(member.getId()) .email(member.getEmail()) .name(member.getName()) - .ImgUrl(member.getImageUrl()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -45,11 +50,4 @@ public ResponseEntity getCurrentUser(UserPrincipal userPrincipal){ return ResponseEntity.ok(apiResponse); } - - - - public MemberDto findById(Long id) { - return memberMapper.findById(id); - } - } diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index aa76976b..c01ccd08 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -32,16 +32,8 @@ public class Member extends BaseEntity { @Email private String email; - private String imageUrl; - private String password; - @Enumerated(EnumType.STRING) - private Provider provider; - - @Enumerated(EnumType.STRING) - private MemberRole memberRole; - private String platformId; @Enumerated(EnumType.STRING) @@ -54,11 +46,12 @@ public class Member extends BaseEntity { @Column(name = "status") private Status status; - public Member(String email, Platform platform, Status status) { + public Member(String email, Platform platform, Status status, String memberNumber) { this.email = email; this.platform = platform; this.platformId = platformId; this.status = status; + this.memberNumber = memberNumber; } public boolean isRegisteredOAuthMember() { @@ -69,7 +62,4 @@ public void updateName(String name) { this.name = name; } - public void updateImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/MemberRole.java b/src/main/java/com/ttubeog/domain/member/domain/MemberRole.java deleted file mode 100644 index 74b0abfe..00000000 --- a/src/main/java/com/ttubeog/domain/member/domain/MemberRole.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ttubeog.domain.member.domain; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -public enum MemberRole { - ADMIN("ROLE_ADMIN"), - USER("ROLE_USER"); - - private String value; - - MemberRole(String value) { - this.value = value; - } - - public String getRole() { - return value; - } -} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/domain/Provider.java b/src/main/java/com/ttubeog/domain/member/domain/Provider.java deleted file mode 100644 index adf6227d..00000000 --- a/src/main/java/com/ttubeog/domain/member/domain/Provider.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ttubeog.domain.member.domain; - -public enum Provider { - KAKAO, - APPLE -} diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index f8a1c519..3bedd910 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -25,7 +25,6 @@ public static MemberDetailRes toDto(Member member) { .id(member.getId()) .name(member.getName()) .email(member.getEmail()) - .ImgUrl(member.getImageUrl()) .build(); } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 5856d0ee..0a8aac4b 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -2,6 +2,8 @@ import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.exception.NotFoundMemberException; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.response.MemberDetailRes; @@ -15,7 +17,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -27,8 +31,7 @@ @RequiredArgsConstructor @RequestMapping("/api/v1/member") public class MemberController { - - private final MemberRepository memberRepository; + private final MemberService memberService; @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") @ApiResponses(value = { @@ -36,14 +39,10 @@ public class MemberController { @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("") - public Optional getCurrentMember( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal + public ResponseEntity getCurrentMember( + HttpServletRequest request ) { - final long memberId = SecurityUtil.getCurrentMemeberId(); - Optional member = memberRepository.findById(memberId); - if (member == null) { - throw new NotFoundMemberException(); - } - return member; + + return memberService.getCurrentUser(request); } } diff --git a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java index 107d4720..a7daf1ce 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java @@ -1,7 +1,6 @@ package com.ttubeog.global.config.security.token; -import com.ttubeog.domain.member.domain.MemberRole; -import com.ttubeog.domain.member.dto.MemberDto; +import com.ttubeog.domain.member.domain.Member; import lombok.Getter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -16,31 +15,27 @@ @Getter public class UserPrincipal implements OAuth2User, UserDetails{ - private final MemberDto member; + private final Member member; private final Long id; private final String email; private final String password; - private final Collection authorities; @Getter private Map attributes; - public UserPrincipal(MemberDto member, Long id, String email, String password, Collection authorities) { + public UserPrincipal(Member member, Long id, String email, String password) { this.member = member; this.id = id; this.email = email; this.password = password; - this.authorities = authorities; } - public static UserPrincipal create(MemberDto member) { - List authorities = Collections.singletonList(new SimpleGrantedAuthority(MemberRole.USER.getRole())); + public static UserPrincipal create(Member member) { return new UserPrincipal( member, member.getId(), member.getEmail(), - member.getPassword(), - authorities + member.getPassword() ); } @@ -48,7 +43,7 @@ public static UserPrincipal create(MemberDto member) { public void setAttributes(Map attributes) { this.attributes = attributes; } - + public Long getId() { return id; } @@ -69,7 +64,7 @@ public Map getAttributes() { @Override public Collection getAuthorities() { - return authorities; + return null; } @Override @@ -106,5 +101,5 @@ public boolean isCredentialsNonExpired() { public boolean isEnabled() { return true; } - + } From d4d20f7a2f114c54e12f78e40e145469b4cc4ff9 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 2 Feb 2024 17:41:22 +0900 Subject: [PATCH 139/356] =?UTF-8?q?[Feat]=20=EB=A9=A4=EB=B2=84=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EC=84=A4=EC=A0=95=20=EC=97=AC=EB=B6=80?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20isRegistered=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/auth/service/AuthService.java | 10 ++++------ .../domain/member/application/MemberService.java | 3 +-- .../java/com/ttubeog/domain/member/domain/Member.java | 6 +++--- .../java/com/ttubeog/domain/member/dto/MemberDto.java | 2 +- .../domain/member/dto/response/MemberDetailRes.java | 2 +- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 2764b9a2..03bed6c7 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -6,7 +6,6 @@ import com.ttubeog.domain.auth.domain.Token; import com.ttubeog.domain.auth.dto.KakaoInfoDto; import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; -import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.NotFoundMemberException; @@ -15,16 +14,12 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import java.util.Map; import java.util.Optional; @Service @@ -59,6 +54,8 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { if (memberData.isEmpty()) { member = Member.builder() .memberNumber(String.valueOf(memberInfo.getId())) + .platform(Platform.KAKAO) + .status(Status.ACTIVE) .build(); memberRepository.save(member); @@ -69,7 +66,8 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { String refreshToken = jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); - if (memberData.isEmpty()) { + String memberName = memberLoginData.get().getNickname(); + if (memberName == null || memberName.isEmpty()) { return KakaoTokenResponse.builder() .accessToken(jwtTokenProvider.createAccessToken( memberLoginData.get().getId())) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index d350fc53..37711a11 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -39,8 +39,7 @@ public ResponseEntity getCurrentUser(HttpServletRequest request){ MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) - .email(member.getEmail()) - .name(member.getName()) + .name(member.getNickname()) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index c01ccd08..230a1083 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -23,7 +23,7 @@ public class Member extends BaseEntity { private String oAuthId; - private String name; + private String nickname; @Size(max = 45) @NotNull @@ -55,11 +55,11 @@ public Member(String email, Platform platform, Status status, String memberNumbe } public boolean isRegisteredOAuthMember() { - return name != null; + return nickname != null; } public void updateName(String name) { - this.name = name; + this.nickname = name; } } diff --git a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java index f68677ea..0d56d0d3 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/MemberDto.java @@ -23,7 +23,7 @@ public static MemberDto toEntity(Member member) { return MemberDto.builder() .id(member.getId()) .email(member.getEmail()) - .name(member.getName()) + .name(member.getNickname()) .platform(member.getPlatform()) .build(); } diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index 3bedd910..3fc80933 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -23,7 +23,7 @@ public class MemberDetailRes { public static MemberDetailRes toDto(Member member) { return MemberDetailRes.builder() .id(member.getId()) - .name(member.getName()) + .name(member.getNickname()) .email(member.getEmail()) .build(); } From 9709b3464323a3c0376473b4c4fd39fd0fc856c7 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 2 Feb 2024 18:13:51 +0900 Subject: [PATCH 140/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20API=20=EA=B5=AC=ED=98=84=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityUtil.java | 1 - .../member/application/MemberService.java | 38 ++++++++++++++----- .../domain/repository/MemberRepository.java | 6 ++- .../dto/request/ProduceNicknameRequest.java | 13 +++++++ .../member/presentation/MemberController.java | 27 ++++++------- .../config/security/token/UserPrincipal.java | 3 -- 6 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/member/dto/request/ProduceNicknameRequest.java diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java index bb7c0c34..1da8e405 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityUtil.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.auth.config; -import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.config.security.token.UserPrincipal; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 37711a11..94ab96bc 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,20 +1,15 @@ package com.ttubeog.domain.member.application; -import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.member.dto.MemberDto; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; -import com.ttubeog.domain.member.mapper.MemberMapper; +import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; +import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +25,7 @@ public class MemberService { // 현재 유저 조회 - public ResponseEntity getCurrentUser(HttpServletRequest request){ + public ResponseEntity getCurrentUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); Optional checkUser = memberRepository.findById(memberId); @@ -49,4 +44,27 @@ public ResponseEntity getCurrentUser(HttpServletRequest request){ return ResponseEntity.ok(apiResponse); } -} + + // 닉네임 설정 + @Transactional + public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); + + Optional checkUser = memberRepository.findById(memberId); + + Member member = checkUser.get(); + + MemberDetailRes memberDetailRes = MemberDetailRes.builder() + .id(member.getId()) + .name(member.getNickname()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(memberDetailRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 81b3a920..f9889abb 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,11 +1,12 @@ package com.ttubeog.domain.member.domain.repository; import com.ttubeog.domain.auth.domain.Platform; -import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import io.lettuce.core.dynamic.annotation.Param; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -32,4 +33,7 @@ public interface MemberRepository extends JpaRepository{ @Query("select m.id from Member m where m.platform = :platform and m.platformId = :platformId") Optional findIdByPlatformAndPlatformId(Platform platform, String platformId); + @Modifying + @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") + void updateUserNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); } diff --git a/src/main/java/com/ttubeog/domain/member/dto/request/ProduceNicknameRequest.java b/src/main/java/com/ttubeog/domain/member/dto/request/ProduceNicknameRequest.java new file mode 100644 index 00000000..588c2489 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/dto/request/ProduceNicknameRequest.java @@ -0,0 +1,13 @@ +package com.ttubeog.domain.member.dto.request; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "ProduceNicknameRequest") +public class ProduceNicknameRequest { + + @Schema(description = "닉네임", example = "푸") + private String nickname; +} diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 0a8aac4b..957af597 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,17 +1,10 @@ package com.ttubeog.domain.member.presentation; -import com.ttubeog.domain.auth.config.SecurityUtil; -import com.ttubeog.domain.auth.exception.NotFoundMemberException; -import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.member.application.MemberService; -import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -20,11 +13,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; +import org.springframework.web.bind.annotation.*; @Tag(name = "Member", description = "Member API") @RestController @@ -45,4 +34,16 @@ public ResponseEntity getCurrentMember( return memberService.getCurrentUser(request); } + + @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 닉네임을 설정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @PostMapping(value = "/nickname") + public ResponseEntity postMemberNickname( + HttpServletRequest request, @RequestBody ProduceNicknameRequest produceNicknameRequest + ) { + return memberService.postMemberNickname(request, produceNicknameRequest); + } } diff --git a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java index a7daf1ce..7470db7c 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java @@ -3,13 +3,10 @@ import com.ttubeog.domain.member.domain.Member; import lombok.Getter; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Map; @Getter From 5214571f9a6fee7b25c570fb110aaf4638be69ea Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sat, 3 Feb 2024 23:48:58 +0900 Subject: [PATCH 141/356] =?UTF-8?q?Feat:=20=ED=98=84=EC=9E=AC=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=A1=B0=ED=9A=8C=20=EB=B0=A9=EB=B2=95=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 32 ++++++++++++------- .../presentation/BenefitController.java | 30 ++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 5f1e2c42..30ccb32e 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; @@ -22,6 +23,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -42,12 +44,14 @@ public class BenefitService { private final BenefitRepository benefitRepository; private final StoreRepository storeRepository; private final MemberBenefitRepository memberBenefitRepository; + private final JwtTokenProvider jwtTokenProvider; // 혜택 생성 @Transactional - public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { + public ResponseEntity createBenefit(HttpServletRequest request, CreateBenefitReq createBenefitReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); @@ -78,9 +82,10 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi // 혜택 삭제 @Transactional - public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + public ResponseEntity deleteBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 @@ -97,9 +102,10 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit //혜택 수정 @Transactional - public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { + public ResponseEntity updateBenefit(HttpServletRequest request, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 @@ -123,9 +129,10 @@ public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefi //게임 성공 후 혜택 저장 @Transactional - public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //유저에게 이미 있는 benefit인지 확인 @@ -166,9 +173,10 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId //혜택 사용 @Transactional - public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { + public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //만료기간 안에 혜택은 오직 한개 @@ -202,8 +210,8 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ResponseEntity findMyBenefit(Integer page) throws JsonProcessingException { - final long memberId = SecurityUtil.getCurrentMemeberId(); + public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Page memberBenefitPage = memberBenefitRepository.findAllByMember(member, PageRequest.of(page, 10)); diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 91411e87..f49660b2 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -20,6 +20,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import jakarta.validation.Valid; @@ -41,11 +42,10 @@ public class BenefitController { }) @PostMapping public ResponseEntity createBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateBenefitReq createBenefitReq ) throws JsonProcessingException { - return benefitService.createBenefit(userPrincipal, createBenefitReq); + return benefitService.createBenefit(request, createBenefitReq); } //혜택 삭제 @@ -56,11 +56,10 @@ public ResponseEntity createBenefit( }) @DeleteMapping("/{benefitId}") public ResponseEntity deleteBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.deleteBenefit(userPrincipal, benefitId); + return benefitService.deleteBenefit(request, benefitId); } //혜택 수정 @@ -71,11 +70,10 @@ public ResponseEntity deleteBenefit( }) @PatchMapping public ResponseEntity updateBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateBenefitReq updateBenefitReq ) throws JsonProcessingException { - return benefitService.updateBenefit(userPrincipal, updateBenefitReq); + return benefitService.updateBenefit(request, updateBenefitReq); } //게임 성공 후 혜택 저장 @@ -86,11 +84,10 @@ public ResponseEntity updateBenefit( }) @PatchMapping("/{benefitId}") public ResponseEntity saveBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.saveBenefit(userPrincipal, benefitId); + return benefitService.saveBenefit(request, benefitId); } //혜택 사용 @@ -101,11 +98,10 @@ public ResponseEntity saveBenefit( }) @PatchMapping("{benefitId}/use") public ResponseEntity useBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.useBenefit(userPrincipal, benefitId); + return benefitService.useBenefit(request, benefitId); } //혜택 조회 @@ -116,9 +112,9 @@ public ResponseEntity useBenefit( }) @GetMapping public ResponseEntity findMyBenefit( - @Parameter(description = "Accesstoken을 입력해주세요.", required = true) + HttpServletRequest request, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { - return benefitService.findMyBenefit(page); + return benefitService.findMyBenefit(request, page); } } From 4ff50b8ec06f103e508523e20e4a42ef3b3901d9 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 5 Feb 2024 02:03:41 +0900 Subject: [PATCH 142/356] =?UTF-8?q?[Feat]=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20Controller=20=EA=B5=AC=ED=98=84=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/controller/AuthController.java | 9 +++------ .../auth/dto/request/ReissueLoginRequest.java | 14 ++++++++++++++ .../ttubeog/domain/auth/service/AuthService.java | 1 + .../domain/member/application/MemberService.java | 7 ++++++- .../member/presentation/MemberController.java | 14 +++++++++++++- 5 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java index cf4a4e48..cc6c549a 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; +import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.security.JwtTokenProvider; @@ -12,10 +13,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "OAuth", description = "로그인") @RestController @@ -28,9 +26,8 @@ public class AuthController { @Operation(summary = "카카오 OAuth 로그인") @PostMapping("/login/kakao") public KakaoTokenResponse loginKakao(@RequestBody @Valid KakaoLoginRequest kakaoLoginRequest, HttpServletRequest request) { - KakaoTokenResponse reissueTokenResponseDto = authService.kakaoOAuthLogin(kakaoLoginRequest.getAccessToken()); - return reissueTokenResponseDto; + return authService.kakaoOAuthLogin(kakaoLoginRequest.getAccessToken()); } @Operation(summary = "애플 OAuth 로그인") diff --git a/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java new file mode 100644 index 00000000..3ab07c43 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.auth.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@ToString +public class ReissueLoginRequest { + + @NotBlank + private String reissueToken; +} diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 03bed6c7..1749f908 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -17,6 +17,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 94ab96bc..9fe744d2 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; @@ -67,4 +67,9 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } + + // 토큰 재발급 설정 + public ResponseEntity getMemberReissueToken(HttpServletRequest request, ReissueLoginRequest reissueLoginRequest) { + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 957af597..4548417d 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.presentation; +import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; @@ -35,7 +36,7 @@ public ResponseEntity getCurrentMember( return memberService.getCurrentUser(request); } - @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 닉네임을 설정합니다.") + @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), @@ -46,4 +47,15 @@ public ResponseEntity postMemberNickname( ) { return memberService.postMemberNickname(request, produceNicknameRequest); } + + @Operation(summary = "토큰 재발급", description = "현재 접속된 멤버의 토큰을 재발급 합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "토큰 재발급 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "토큰 재발급 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @GetMapping("/login/reissue") + public ResponseEntity loginReissue(HttpServletRequest request, @RequestBody ReissueLoginRequest reissueLoginRequest) { + // TODO + return null; + } } From 14e6d11fc58b35bb1f137eb3efee1c7f49b677fc Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:21:52 +0900 Subject: [PATCH 143/356] =?UTF-8?q?Feat:=20BenefitServer=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=EC=9C=A0=EC=A0=80=20=ED=98=B8=EC=B6=9C=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index ccef61ba..e38bf60e 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -26,6 +26,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.hibernate.Hibernate; import org.springframework.data.domain.Page; @@ -52,9 +53,9 @@ public class BenefitService { // 혜택 생성 @Transactional - public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createBenefit(HttpServletRequest request, CreateBenefitReq createBenefitReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); @@ -85,9 +86,9 @@ public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefi // 혜택 삭제 @Transactional - public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity deleteBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 @@ -104,9 +105,9 @@ public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefit //혜택 수정 @Transactional - public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateBenefit(HttpServletRequest request, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 @@ -130,9 +131,9 @@ public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefi //게임 성공 후 혜택 저장 @Transactional - public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 @@ -171,9 +172,9 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId //혜택 사용 @Transactional - public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //만료기간 안에 혜택은 오직 한개 @@ -207,9 +208,9 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Page memberBenefitPage = memberBenefitRepository.findAllByMember(member, PageRequest.of(page, 10)); @@ -235,9 +236,9 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page } //혜택ID로 게임 조회 - public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findGames(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); List games = gameRepository.findAllByBenefit(benefit); From d4100ae360cc7bc1c77c8464692c4421d91bb595 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:24:41 +0900 Subject: [PATCH 144/356] =?UTF-8?q?Chore:=20GameService=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=EC=9C=A0=EC=A0=80=20=ED=98=B8=EC=B6=9C=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 83544787..ff6b9633 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -15,6 +15,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.hibernate.Hibernate; import org.springframework.http.ResponseEntity; @@ -35,9 +36,9 @@ public class GameService { // 선물게임 생성 @Transactional - public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq createGiftReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(createGiftReq.getBenefitId() ).orElseThrow(NonExistentBenefitException::new); @@ -78,9 +79,9 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c // 농구게임 생성 @Transactional - public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBasketballReq createBasketballReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(createBasketballReq.getBenefitId() ).orElseThrow(NonExistentBenefitException::new); @@ -123,9 +124,9 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas //돌림판 게임 생성 @Transactional - public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRouletteReq createRouletteReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(createRouletteReq.getBenefitId() ).orElseThrow(NonExistentBenefitException::new); @@ -162,9 +163,9 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule //선물게임 수정 @Transactional - public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq updateGiftReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); @@ -186,9 +187,9 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u //농구게임 수정 @Transactional - public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); @@ -212,9 +213,9 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas //돌림판 게임 수정 @Transactional - public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); rouletteGame.updateOptions(updateRouletteReq.getOptions()); @@ -234,9 +235,9 @@ public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRoule //게임 삭제 @Transactional - public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity deleteGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); gameRepository.delete(game); @@ -251,9 +252,9 @@ public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) th //게임 조회 @Transactional - public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); FindGameRes.FindGameResBuilder builder = FindGameRes.builder() From 01f9c02826e6be2ceaaa216c93b11ff7d222bb23 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:26:58 +0900 Subject: [PATCH 145/356] =?UTF-8?q?Chore:=20GameController=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=EC=9C=A0=EC=A0=80=20=ED=98=B8=EC=B6=9C=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/presentation/GameController.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 29cb6f75..282c9715 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -35,10 +36,10 @@ public class GameController { }) @PostMapping("/gift") public ResponseEntity createGift( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateGiftReq createGiftReq ) throws JsonProcessingException { - return gameService.createGift(userPrincipal, createGiftReq); + return gameService.createGift(request, createGiftReq); } //농구 게임 생성 @@ -49,10 +50,10 @@ public ResponseEntity createGift( }) @PostMapping("/basketball") public ResponseEntity createBasketball( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateBasketballReq createBasketballReq ) throws JsonProcessingException { - return gameService.createBasketBall(userPrincipal, createBasketballReq); + return gameService.createBasketBall(request, createBasketballReq); } //돌림판 게임 생성 @@ -63,10 +64,10 @@ public ResponseEntity createBasketball( }) @PostMapping("/roulette") public ResponseEntity createRoulette( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateRouletteReq createRouletteReq ) throws JsonProcessingException { - return gameService.createRoulette(userPrincipal, createRouletteReq); + return gameService.createRoulette(request, createRouletteReq); } //선물 게임 수정 @@ -77,10 +78,10 @@ public ResponseEntity createRoulette( }) @PatchMapping("/gift") public ResponseEntity updateGift( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateGiftReq updateGiftReq ) throws JsonProcessingException { - return gameService.updateGift(userPrincipal, updateGiftReq); + return gameService.updateGift(request, updateGiftReq); } //농구 게임 수정 @@ -91,10 +92,10 @@ public ResponseEntity updateGift( }) @PatchMapping("/basketball") public ResponseEntity updateBasketball( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateBasketballReq updateBasketballReq ) throws JsonProcessingException { - return gameService.updateBasketball(userPrincipal, updateBasketballReq); + return gameService.updateBasketball(request, updateBasketballReq); } //돌림판 게임 수정 @@ -105,10 +106,10 @@ public ResponseEntity updateBasketball( }) @PatchMapping("/roulette") public ResponseEntity updateRoulette( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateRouletteReq updateRouletteReq ) throws JsonProcessingException { - return gameService.updateRoulette(userPrincipal, updateRouletteReq); + return gameService.updateRoulette(request, updateRouletteReq); } //게임 삭제 @@ -119,10 +120,10 @@ public ResponseEntity updateRoulette( }) @DeleteMapping("/{gameId}") public ResponseEntity deleteGame( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.deleteGame(userPrincipal, gameId); + return gameService.deleteGame(request, gameId); } //게임 조회 @@ -133,10 +134,10 @@ public ResponseEntity deleteGame( }) @GetMapping("/{gameId}") public ResponseEntity findGame( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.findGame(userPrincipal, gameId); + return gameService.findGame(request, gameId); } } From d625ffd3b8775d7e169ffbdac04ac024d943620d Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:28:35 +0900 Subject: [PATCH 146/356] =?UTF-8?q?Chore:=20BenefitController=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=EC=9C=A0=EC=A0=80=20=ED=98=B8=EC=B6=9C=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/BenefitController.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 2495dcc3..e11cbfaa 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -18,6 +18,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import jakarta.validation.Valid; @@ -39,10 +40,10 @@ public class BenefitController { }) @PostMapping public ResponseEntity createBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateBenefitReq createBenefitReq ) throws JsonProcessingException { - return benefitService.createBenefit(userPrincipal, createBenefitReq); + return benefitService.createBenefit(request, createBenefitReq); } //혜택 삭제 @@ -53,10 +54,10 @@ public ResponseEntity createBenefit( }) @DeleteMapping("/{benefitId}") public ResponseEntity deleteBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.deleteBenefit(userPrincipal, benefitId); + return benefitService.deleteBenefit(request, benefitId); } //혜택 수정 @@ -67,10 +68,10 @@ public ResponseEntity deleteBenefit( }) @PatchMapping public ResponseEntity updateBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateBenefitReq updateBenefitReq ) throws JsonProcessingException { - return benefitService.updateBenefit(userPrincipal, updateBenefitReq); + return benefitService.updateBenefit(request, updateBenefitReq); } //게임 성공 후 혜택 저장 @@ -81,10 +82,10 @@ public ResponseEntity updateBenefit( }) @PatchMapping("/{benefitId}") public ResponseEntity saveBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.saveBenefit(userPrincipal, benefitId); + return benefitService.saveBenefit(request, benefitId); } //혜택 사용 @@ -95,10 +96,10 @@ public ResponseEntity saveBenefit( }) @PatchMapping("{benefitId}/use") public ResponseEntity useBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.useBenefit(userPrincipal, benefitId); + return benefitService.useBenefit(request, benefitId); } //혜택 조회 @@ -109,10 +110,10 @@ public ResponseEntity useBenefit( }) @GetMapping public ResponseEntity findMyBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { - return benefitService.findMyBenefit(userPrincipal, page); + return benefitService.findMyBenefit(request, page); } //혜택으로 모든 게임 조회 @@ -123,9 +124,9 @@ public ResponseEntity findMyBenefit( }) @GetMapping("/{benefitId}/game") public ResponseEntity findGames( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.findGames(userPrincipal, benefitId); + return benefitService.findGames(request, benefitId); } } From db3b0f0eb144307284a6c43dc5fbe0711b41a1a0 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:37:14 +0900 Subject: [PATCH 147/356] =?UTF-8?q?Chore:=20GameService=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/game/application/GameService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index ff6b9633..3f98631d 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -33,6 +33,7 @@ public class GameService { private final GiftGameRepository giftGameRepository; private final BasketBallRepository basketBallRepository; private final RouletteRepository rouletteRepository; + private final JwtTokenProvider jwtTokenProvider; // 선물게임 생성 @Transactional From 735e571f3327b2072b4e8ef36c2c2f7dff51e847 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:40:36 +0900 Subject: [PATCH 148/356] =?UTF-8?q?Chore:=20GameService=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/game/application/GameService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 3f98631d..f87b9366 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.game.application; import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; From 8cc973b1793194865a2a7e553c70421d466183da Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 02:44:12 +0900 Subject: [PATCH 149/356] =?UTF-8?q?Chore:=20build.gradle=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 31d7d21e..4b00d61a 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" -// runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' @@ -73,4 +72,4 @@ tasks.named('test') { jar { enabled = false -} \ No newline at end of file +} From 25055321b7b2b5eb612ee54467e47a4967f3377b Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 5 Feb 2024 15:51:24 +0900 Subject: [PATCH 150/356] =?UTF-8?q?[Feat]=20JWT=20provider=20=EB=A6=AC?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=84=A4=EC=A0=95=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/security/JwtTokenProvider.java | 25 ++++++++++++------- .../member/presentation/MemberController.java | 6 +++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index d8c34014..67141adf 100644 --- a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -13,23 +13,29 @@ public class JwtTokenProvider { private final String secretKey; private final long validityAccessTokenInMilliseconds; + private final long validityRefreshTokenInMilliseconds; private final JwtParser jwtParser; - private final long refreshTokenTime = 1L * 60 * 1000 * 2; public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey, @Value("${jwt.access-expired-time}") - long validityAccessTokenInMilliseconds) { + long validityAccessTokenInMilliseconds, + @Value("${jwt.refresh-expired-time}") + long validityRefreshTokenInMilliseconds) { this.secretKey = secretKey; this.validityAccessTokenInMilliseconds = validityAccessTokenInMilliseconds; + this.validityRefreshTokenInMilliseconds = validityRefreshTokenInMilliseconds; this.jwtParser = Jwts.parser().setSigningKey(secretKey); } public String createAccessToken(Long memberId) { + Claims claims = Jwts.claims().setSubject(String.valueOf(memberId)); + Date now = new Date(); Date validity = new Date(now.getTime() + validityAccessTokenInMilliseconds); return Jwts.builder() + .setClaims(claims) .setSubject(String.valueOf(memberId)) .setIssuedAt(now) .setExpiration(validity) @@ -38,13 +44,14 @@ public String createAccessToken(Long memberId) { } - public String createRereshToken(Long userId) { // 토큰 생성 - Claims claims = Jwts.claims().setSubject(String.valueOf(userId)); - + public String createRereshToken(Long memberId) { // 토큰 생성 + Claims claims = Jwts.claims().setSubject(String.valueOf(memberId)); Date now = new Date(); + String token = Jwts.builder() + .setClaims(claims) .setIssuedAt(now) - .setExpiration(new Date(now.getTime() + refreshTokenTime)) + .setExpiration(new Date(now.getTime() + validityRefreshTokenInMilliseconds)) .signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘, secret 값 세팅 .compact(); @@ -93,9 +100,9 @@ public String getPayload(String token) { } public Long getMemberId(HttpServletRequest request) { - String token = resolveToken(request); // 클라이언트의 토큰을 가져옴 - String userId = getPayload(token); // 토큰에서 사용자 ID를 추출 + String token = resolveToken(request); + String memberId = getPayload(token); - return Long.valueOf(userId); // 사용자 ID를 Long으로 변환하여 반환 + return Long.valueOf(memberId); } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 4548417d..96855801 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -54,8 +54,10 @@ public ResponseEntity postMemberNickname( @ApiResponse(responseCode = "400", description = "토큰 재발급 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("/login/reissue") - public ResponseEntity loginReissue(HttpServletRequest request, @RequestBody ReissueLoginRequest reissueLoginRequest) { - // TODO + public ResponseEntity loginReissue( + HttpServletRequest request, @RequestBody ReissueLoginRequest reissueLoginRequest + ) { + return null; } } From e8fa7b158150afe540ed55a31c38e4a2286ae7b7 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:11:29 +0900 Subject: [PATCH 151/356] =?UTF-8?q?Chore:=20ENUM=20=EB=8C=80=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/game/domain/GameType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/game/domain/GameType.java b/src/main/java/com/ttubeog/domain/game/domain/GameType.java index 47678acf..373d902f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GameType.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GameType.java @@ -1,5 +1,5 @@ package com.ttubeog.domain.game.domain; public enum GameType { - basketball, roulette, gift + BASKETBALL, ROULETTE, GIFT } From cd4edcef89e3ba5e2be45dbfd675b06b0bda65c0 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:13:30 +0900 Subject: [PATCH 152/356] =?UTF-8?q?Chore:=20ENUM=20=EB=8C=80=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index f87b9366..59620ae6 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -45,13 +45,13 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.gift)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.GIFT)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.gift) + .type(GameType.GIFT) .build(); gameRepository.save(game); @@ -88,13 +88,13 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.basketball)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.BASKETBALL)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.basketball) + .type(GameType.BASKETBALL) .build(); gameRepository.save(game); @@ -133,13 +133,13 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.roulette)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.ROULETTE)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.roulette) + .type(GameType.ROULETTE) .build(); gameRepository.save(game); @@ -263,14 +263,14 @@ public ResponseEntity findGame(HttpServletRequest request, Long gameId) throw .gameId(game.getId()) .type(game.getType()); - if (game.getType() == GameType.basketball) { + if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) .ballCount(game.getBasketballGame().getBallCount()) .successCount(game.getBasketballGame().getSuccessCount()); - } else if (game.getType() == GameType.gift) { + } else if (game.getType() == GameType.GIFT) { builder.timeLimit(game.getGiftGame().getTimeLimit()) .giftCount(game.getGiftGame().getGiftCount()); - } else if (game.getType() == GameType.roulette) { + } else if (game.getType() == GameType.ROULETTE) { Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 builder.options(game.getRouletteGame().getOptions()); } From 6ebe0c33af3b82919f6e9489ac7b7d31854fd11f Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:15:03 +0900 Subject: [PATCH 153/356] =?UTF-8?q?Chore:=20ENUM=20=EB=8C=80=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/benefit/application/BenefitService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 34e7ce5c..44cebd7b 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -250,14 +250,14 @@ public ResponseEntity findGames(HttpServletRequest request, Long benefitId) t .gameId(game.getId()) .type(game.getType()); - if (game.getType() == GameType.basketball) { + if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) .ballCount(game.getBasketballGame().getBallCount()) .successCount(game.getBasketballGame().getSuccessCount()); - } else if (game.getType() == GameType.gift) { + } else if (game.getType() == GameType.GIFT) { builder.timeLimit(game.getGiftGame().getTimeLimit()) .giftCount(game.getGiftGame().getGiftCount()); - } else if (game.getType() == GameType.roulette) { + } else if (game.getType() == GameType.ROULETTE) { Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 builder.options(game.getRouletteGame().getOptions()); } From e182a09f6a76327aade46d6d00d090ac0a7ec939 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 5 Feb 2024 19:33:48 +0900 Subject: [PATCH 154/356] =?UTF-8?q?[Feat]=20MemberService=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EC=9E=AC=EB=B0=9C=EA=B8=89=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 1 - .../auth/dto/request/ReissueLoginRequest.java | 14 -------- .../member/application/MemberService.java | 34 ++++++++++++++++--- .../InvalidAccessTokenExpiredException.java | 6 ++++ .../exception/InvalidMemberException.java | 2 +- .../member/presentation/MemberController.java | 5 ++- 6 files changed, 38 insertions(+), 24 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java create mode 100644 src/main/java/com/ttubeog/domain/member/exception/InvalidAccessTokenExpiredException.java diff --git a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java index cc6c549a..1dda1203 100644 --- a/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java +++ b/src/main/java/com/ttubeog/domain/auth/controller/AuthController.java @@ -2,7 +2,6 @@ import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.request.KakaoLoginRequest; -import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.security.JwtTokenProvider; diff --git a/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java b/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java deleted file mode 100644 index 3ab07c43..00000000 --- a/src/main/java/com/ttubeog/domain/auth/dto/request/ReissueLoginRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ttubeog.domain.auth.dto.request; - -import jakarta.validation.constraints.NotBlank; -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter -@ToString -public class ReissueLoginRequest { - - @NotBlank - private String reissueToken; -} diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 9fe744d2..29bf3a15 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,11 +1,14 @@ package com.ttubeog.domain.member.application; -import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; +import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; +import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; import jakarta.servlet.http.HttpServletRequest; @@ -51,9 +54,9 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); - Optional checkUser = memberRepository.findById(memberId); + Optional checkMember = memberRepository.findById(memberId); - Member member = checkUser.get(); + Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) @@ -69,7 +72,28 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN } // 토큰 재발급 설정 - public ResponseEntity getMemberReissueToken(HttpServletRequest request, ReissueLoginRequest reissueLoginRequest) { - return null; + public ResponseEntity getMemberReissueToken(HttpServletRequest request) { + Long memberId; + + try { + memberId = jwtTokenProvider.getMemberId(request); + } catch (InvalidAccessTokenException | AccessTokenExpiredException e) { + throw e; + } + + Optional checkMember = memberRepository.findById(memberId); + if (checkMember.isEmpty()) { + throw new InvalidMemberException(); // 존재 하지 않는 회원일 경우 + } + + Member member = checkMember.get(); + + // 리프레시 토큰으로 새로운 액세스 토큰 발급 + try { + String newAccessToken = jwtTokenProvider.createAccessToken(memberId); + return ResponseEntity.ok(new ApiResponse(true, newAccessToken)); + } catch (Exception e) { + return ResponseEntity.badRequest().body(new InvalidAccessTokenExpiredException()); + } } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/exception/InvalidAccessTokenExpiredException.java b/src/main/java/com/ttubeog/domain/member/exception/InvalidAccessTokenExpiredException.java new file mode 100644 index 00000000..2c08b155 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/exception/InvalidAccessTokenExpiredException.java @@ -0,0 +1,6 @@ +package com.ttubeog.domain.member.exception; + + +public class InvalidAccessTokenExpiredException extends RuntimeException { + public InvalidAccessTokenExpiredException() { super("새로운 Access Token 생성에 실패하였습니다.");} +} diff --git a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java index c65365c1..b3c1b113 100644 --- a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java +++ b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java @@ -3,7 +3,7 @@ public class InvalidMemberException extends RuntimeException { public InvalidMemberException(){ - super("유저가 올바르지 않습니다."); + super("멤버가 올바르지 않습니다."); } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 96855801..32778328 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.member.presentation; -import com.ttubeog.domain.auth.dto.request.ReissueLoginRequest; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; @@ -55,9 +54,9 @@ public ResponseEntity postMemberNickname( }) @GetMapping("/login/reissue") public ResponseEntity loginReissue( - HttpServletRequest request, @RequestBody ReissueLoginRequest reissueLoginRequest + HttpServletRequest request ) { - return null; + return memberService.getMemberReissueToken(request); } } From c69944f44250dfc823d0545a6fe0b5978de62622 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 5 Feb 2024 19:50:31 +0900 Subject: [PATCH 155/356] =?UTF-8?q?[Feat]=20MemberDetailRes=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EC=97=90=20email,=20imageUrl=20=EC=82=AD=EC=A0=9C,=20?= =?UTF-8?q?platform=20=EC=B6=94=EA=B0=80=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/member/application/MemberService.java | 6 +++--- src/main/java/com/ttubeog/domain/member/domain/Member.java | 2 -- .../domain/member/dto/response/MemberDetailRes.java | 7 +++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 94ab96bc..c83c3877 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.member.application; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; @@ -23,7 +22,6 @@ public class MemberService { private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; - // 현재 유저 조회 public ResponseEntity getCurrentUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -35,6 +33,7 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) .name(member.getNickname()) + .platform(member.getPlatform()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -58,6 +57,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) .name(member.getNickname()) + .platform(member.getPlatform()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -67,4 +67,4 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } -} \ No newline at end of file +} diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 230a1083..7878763d 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -40,8 +40,6 @@ public class Member extends BaseEntity { @Column(name = "platform") private Platform platform; - private String refreshToken; - @Enumerated(EnumType.STRING) @Column(name = "status") private Status status; diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index 3fc80933..b9db943b 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.dto.response; +import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.member.domain.Member; import lombok.AllArgsConstructor; import lombok.Builder; @@ -16,15 +17,13 @@ public class MemberDetailRes { private String name; - private String email; - - private String ImgUrl; + private Platform platform; public static MemberDetailRes toDto(Member member) { return MemberDetailRes.builder() .id(member.getId()) .name(member.getNickname()) - .email(member.getEmail()) + .platform(member.getPlatform()) .build(); } From 6304e97ae03d5f8c291c71b2e9d874df0955e559 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 5 Feb 2024 20:53:47 +0900 Subject: [PATCH 156/356] =?UTF-8?q?[Feat]=20=EB=A9=A4=EB=B2=84=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EC=97=90=20refresh=5Ftoken=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/member/domain/Member.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 7878763d..48338927 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -44,6 +44,10 @@ public class Member extends BaseEntity { @Column(name = "status") private Status status; + @Column(name = "refresh_token") + private String refreshToken; + + public Member(String email, Platform platform, Status status, String memberNumber) { this.email = email; this.platform = platform; From 0992b45b8ffcaa9b7b290958bf67c25e5f532fcc Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 6 Feb 2024 01:10:32 +0900 Subject: [PATCH 157/356] =?UTF-8?q?[Feat]=20DB=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/security/JwtTokenProvider.java | 2 +- .../com/ttubeog/domain/auth/service/AuthService.java | 3 +-- .../java/com/ttubeog/domain/member/domain/Member.java | 2 -- .../global/config/security/token/UserPrincipal.java | 11 ----------- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index 67141adf..4c280527 100644 --- a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -44,7 +44,7 @@ public String createAccessToken(Long memberId) { } - public String createRereshToken(Long memberId) { // 토큰 생성 + public String createRefreshToken(Long memberId) { // 토큰 생성 Claims claims = Jwts.claims().setSubject(String.valueOf(memberId)); Date now = new Date(); diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 1749f908..34413929 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -56,7 +56,6 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { member = Member.builder() .memberNumber(String.valueOf(memberInfo.getId())) .platform(Platform.KAKAO) - .status(Status.ACTIVE) .build(); memberRepository.save(member); @@ -64,7 +63,7 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); - String refreshToken = jwtTokenProvider.createRereshToken(memberLoginData.get().getId()); + String refreshToken = jwtTokenProvider.createRefreshToken(memberLoginData.get().getId()); redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); String memberName = memberLoginData.get().getNickname(); diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 48338927..2d8dd24f 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -32,8 +32,6 @@ public class Member extends BaseEntity { @Email private String email; - private String password; - private String platformId; @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java index 7470db7c..a5e4a162 100644 --- a/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java +++ b/src/main/java/com/ttubeog/global/config/security/token/UserPrincipal.java @@ -16,7 +16,6 @@ public class UserPrincipal implements OAuth2User, UserDetails{ private final Long id; private final String email; - private final String password; @Getter private Map attributes; @@ -24,16 +23,6 @@ public UserPrincipal(Member member, Long id, String email, String password) { this.member = member; this.id = id; this.email = email; - this.password = password; - } - - public static UserPrincipal create(Member member) { - return new UserPrincipal( - member, - member.getId(), - member.getEmail(), - member.getPassword() - ); } From 6f175a3ccda28e928e0fd3a560472ce21b5c8020 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 6 Feb 2024 02:20:29 +0900 Subject: [PATCH 158/356] =?UTF-8?q?[Feat]=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20response=20=EB=B3=80=EA=B2=BD=ED=95=98?= =?UTF-8?q?=EC=97=AC=20API=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C=20(#3?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/AuthService.java | 1 - .../member/application/MemberService.java | 29 ++++++++++++++----- .../member/presentation/MemberController.java | 3 +- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 34413929..42916738 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -17,7 +17,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 641e64de..073d6d20 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,8 +1,10 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.auth.service.RefreshTokenService; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; @@ -25,15 +27,16 @@ public class MemberService { private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; + private final RefreshTokenService refreshTokenService; // 현재 유저 조회 public ResponseEntity getCurrentUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); - Optional checkUser = memberRepository.findById(memberId); - DefaultAssert.isOptionalPresent(checkUser); - Member member = checkUser.get(); + Optional checkMember = memberRepository.findById(memberId); + DefaultAssert.isOptionalPresent(checkMember); + Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) @@ -55,9 +58,9 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); - Optional checkUser = memberRepository.findById(memberId); + Optional checkMember = memberRepository.findById(memberId); - Member member = checkUser.get(); + Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) @@ -73,6 +76,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } + @Transactional // 토큰 재발급 설정 public ResponseEntity getMemberReissueToken(HttpServletRequest request) { Long memberId; @@ -80,7 +84,7 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { try { memberId = jwtTokenProvider.getMemberId(request); } catch (InvalidAccessTokenException | AccessTokenExpiredException e) { - throw e; + throw new InvalidAccessTokenException(); } Optional checkMember = memberRepository.findById(memberId); @@ -93,7 +97,18 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { // 리프레시 토큰으로 새로운 액세스 토큰 발급 try { String newAccessToken = jwtTokenProvider.createAccessToken(memberId); - return ResponseEntity.ok(new ApiResponse(true, newAccessToken)); + String newRefreshToken = jwtTokenProvider.createRefreshToken(memberId); + refreshTokenService.saveTokenInfo(memberId, newRefreshToken, newAccessToken); + + + + OAuthTokenResponse oAuthTokenResponse = new OAuthTokenResponse(newAccessToken, newRefreshToken, member.isRegisteredOAuthMember()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(oAuthTokenResponse) + .build(); + return ResponseEntity.ok(apiResponse); } catch (Exception e) { return ResponseEntity.badRequest().body(new InvalidAccessTokenExpiredException()); } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 32778328..4fadb718 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.presentation; +import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; @@ -49,7 +50,7 @@ public ResponseEntity postMemberNickname( @Operation(summary = "토큰 재발급", description = "현재 접속된 멤버의 토큰을 재발급 합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "토큰 재발급 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "200", description = "토큰 재발급 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = OAuthTokenResponse.class))}), @ApiResponse(responseCode = "400", description = "토큰 재발급 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("/login/reissue") From be281dd3f52c23fb44fe5a704a141fd0a57156bc Mon Sep 17 00:00:00 2001 From: choeun7 Date: Wed, 7 Feb 2024 01:31:03 +0900 Subject: [PATCH 159/356] =?UTF-8?q?Chore:=20ENUM=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=8C=80=EB=AC=B8=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 11 +++++------ .../domain/benefit/domain/BenefitType.java | 2 +- .../repository/MemberBenefitRepository.java | 2 +- .../benefit/dto/request/CreateBenefitReq.java | 2 +- .../benefit/dto/response/CreateBenefitRes.java | 2 +- .../benefit/dto/response/SaveBenefitRes.java | 2 +- .../benefit/dto/response/UpdateBenefitRes.java | 2 +- .../domain/game/application/GameService.java | 18 +++++++++--------- .../ttubeog/domain/game/domain/GameType.java | 2 +- 9 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index ccef61ba..28a4741e 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -21,11 +21,11 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.hibernate.Hibernate; import org.springframework.data.domain.Page; @@ -236,7 +236,6 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page //혜택ID로 게임 조회 public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); List games = gameRepository.findAllByBenefit(benefit); @@ -247,14 +246,14 @@ public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) .gameId(game.getId()) .type(game.getType()); - if (game.getType() == GameType.basketball) { + if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) .ballCount(game.getBasketballGame().getBallCount()) .successCount(game.getBasketballGame().getSuccessCount()); - } else if (game.getType() == GameType.gift) { + } else if (game.getType() == GameType.GIFT) { builder.timeLimit(game.getGiftGame().getTimeLimit()) .giftCount(game.getGiftGame().getGiftCount()); - } else if (game.getType() == GameType.roulette) { + } else if (game.getType() == GameType.ROULETTE) { Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 builder.options(game.getRouletteGame().getOptions()); } @@ -285,4 +284,4 @@ public void autoCheckExpired() { } } } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java b/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java index 41dcbc5f..9ed3f272 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/BenefitType.java @@ -1,5 +1,5 @@ package com.ttubeog.domain.benefit.domain; public enum BenefitType { - sale, plus, gift + SALE, PLUS, GIFT } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 9494161c..c76aee9d 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -22,4 +22,4 @@ public interface MemberBenefitRepository extends JpaRepository findAllByExpiredFalse(); Page findAllByMember(Member member, PageRequest pageRequest); -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java index 0c9dc671..c42256cf 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java @@ -16,7 +16,7 @@ public class CreateBenefitReq { @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; - @Schema(description = "혜택타입", example = "sale") + @Schema(description = "혜택타입", example = "SALE") private BenefitType type; } diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java index b7190e55..b2270541 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java @@ -17,7 +17,7 @@ public class CreateBenefitRes { @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; - @Schema(description = "혜택타입", example = "sale") + @Schema(description = "혜택타입", example = "SALE") private BenefitType type; @Builder diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java index 24edb287..81cd9e1b 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -22,7 +22,7 @@ public class SaveBenefitRes { @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; - @Schema(description = "혜택타입", example = "sale") + @Schema(description = "혜택타입", example = "SALE") private BenefitType type; @Schema(description = "사용 여부", example = "false") diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java index 0bb4044f..7883dc74 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java @@ -17,7 +17,7 @@ public class UpdateBenefitRes { @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; - @Schema(description = "혜택타입", example = "sale") + @Schema(description = "혜택타입", example = "SALE") private BenefitType type; @Builder diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 83544787..961d148e 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -42,13 +42,13 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.gift)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.GIFT)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.gift) + .type(GameType.GIFT) .build(); gameRepository.save(game); @@ -85,13 +85,13 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.basketball)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.BASKETBALL)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.basketball) + .type(GameType.BASKETBALL) .build(); gameRepository.save(game); @@ -130,13 +130,13 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule ).orElseThrow(NonExistentBenefitException::new); //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.roulette)) { + if (gameRepository.existsByBenefitAndType(benefit, GameType.ROULETTE)) { throw new OverlappingGameException(); } Game game = Game.builder() .benefit(benefit) - .type(GameType.roulette) + .type(GameType.ROULETTE) .build(); gameRepository.save(game); @@ -260,14 +260,14 @@ public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) thro .gameId(game.getId()) .type(game.getType()); - if (game.getType() == GameType.basketball) { + if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) .ballCount(game.getBasketballGame().getBallCount()) .successCount(game.getBasketballGame().getSuccessCount()); - } else if (game.getType() == GameType.gift) { + } else if (game.getType() == GameType.GIFT) { builder.timeLimit(game.getGiftGame().getTimeLimit()) .giftCount(game.getGiftGame().getGiftCount()); - } else if (game.getType() == GameType.roulette) { + } else if (game.getType() == GameType.ROULETTE) { Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 builder.options(game.getRouletteGame().getOptions()); } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GameType.java b/src/main/java/com/ttubeog/domain/game/domain/GameType.java index 47678acf..373d902f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GameType.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GameType.java @@ -1,5 +1,5 @@ package com.ttubeog.domain.game.domain; public enum GameType { - basketball, roulette, gift + BASKETBALL, ROULETTE, GIFT } From 9c030876ee2407932d52eac813e99c7e83dd7576 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Wed, 7 Feb 2024 23:39:25 +0900 Subject: [PATCH 160/356] =?UTF-8?q?[Feat]=20Place=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/place/domain/PlaceType.java | 17 ++++++ .../domain/repository/PlaceRepository.java | 4 ++ .../place/dto/response/GetAllPlaceRes.java | 61 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/place/domain/PlaceType.java create mode 100644 src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java create mode 100644 src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java diff --git a/src/main/java/com/ttubeog/domain/place/domain/PlaceType.java b/src/main/java/com/ttubeog/domain/place/domain/PlaceType.java new file mode 100644 index 00000000..0e35c121 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/domain/PlaceType.java @@ -0,0 +1,17 @@ +package com.ttubeog.domain.place.domain; + +import lombok.Builder; +import lombok.Data; + +@Data +public class PlaceType { + + private boolean store; + private boolean spot; + + @Builder + public PlaceType(boolean store, boolean spot) { + this.store = store; + this.spot = spot; + } +} diff --git a/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java b/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java new file mode 100644 index 00000000..9b2e31b6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.place.domain.repository; + +public interface PlaceRepository { +} diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java new file mode 100644 index 00000000..0074aac3 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -0,0 +1,61 @@ +package com.ttubeog.domain.place.dto.response; + +import com.ttubeog.domain.place.domain.PlaceType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class GetAllPlaceRes { + + @Schema(description = "장소 ID") + private Long placeId; + + @Schema(description = "매장 또는 산책스팟") + private PlaceType placeType; + + @Schema(description = "등록유저 ID") + private Long memberId; + + @Schema(description = "장소 이름") + private String name; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "대표 이미지") + private String image; + + @Schema(description = "별점") + private Float stars; + + @Schema(description = "방명록 수") + private Integer guestbookCount; + + @Schema(description = "좋아요 여부") + private Boolean isFavorited; + + @Schema(description = "생성 시간") + private LocalDateTime createdAt; + + @Builder + public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Float latitude, Float longitude, + String image, Float stars, Integer guestbookCount, Boolean isFavorited, LocalDateTime createdAt) { + this.placeId = placeId; + this.placeType = placeType; + this.memberId = memberId; + this.name = name; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.stars = stars; + this.guestbookCount = guestbookCount; + this.isFavorited = isFavorited; + this.createdAt = createdAt; + } +} From 7541aa5d2ce86c6f407fa5eea2d2c4b28b1b77f3 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Wed, 7 Feb 2024 23:40:27 +0900 Subject: [PATCH 161/356] =?UTF-8?q?[Feat]=20=EC=A0=84=EC=B2=B4=20=EC=9E=A5?= =?UTF-8?q?=EC=86=8C=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 106 ++++++++++++++++++ .../place/presentation/PlaceController.java | 36 ++++++ 2 files changed, 142 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/place/application/PlaceService.java create mode 100644 src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java new file mode 100644 index 00000000..3b5163d2 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -0,0 +1,106 @@ +package com.ttubeog.domain.place.application; + +import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.likes.domain.repository.LikesRepository; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.place.domain.PlaceType; +import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.global.payload.ApiResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + + +@RequiredArgsConstructor +@Service +@Transactional(readOnly = true) +public class PlaceService { + + private final MemberRepository memberRepository; + private final StoreRepository storeRepository; + private final SpotRepository spotRepository; + private final LikesRepository likesRepository; + + public List getAllPlaceResList() { + + List places = new ArrayList<>(); + + List stores = storeRepository.findAll(); + places.addAll(stores.stream().map(this::mapStoreToDto).collect(Collectors.toList())); + // List spots = spotRepository.findAll(); + // places.addAll(spots.stream().map(this::mapSpotToDto).collect(Collectors.toList())); + + return places; + } + + private GetAllPlaceRes mapStoreToDto(Store store) { + + final long memberId = SecurityUtil.getCurrentMemeberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Boolean storeLiked = likesRepository.existsByMemberIdAndStoreId(memberId, store.getId()); + PlaceType placeType = new PlaceType(true, false); + + return GetAllPlaceRes.builder() + .placeId(store.getId()) + .placeType(placeType) + .memberId(store.getMember().getId()) + .name(store.getName()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + //.image(store.getImage()) + .stars(store.getStars()) + // .guestbookCount(guestRepository.countByStoreId(store.getID())) + .isFavorited(storeLiked) + .createdAt(store.getCreatedAt()) + .build(); + } + + /*private GetAllPlaceRes mapSpotToDto(Spot spot) { + + final long memberId = SecurityUtil.getCurrentMemberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Boolean spotLiked = likesRepository.existsByMemberIdAndSpotId(memberId, spot.getId()); + PlaceType placeType = new PlaceType(false, true); + + return GetAllPlaceRes.builder() + .placeId(spot.getId()) + .placeType(placeType) + .memberId(spot.getMember().getId()) + .name(spot.getName()) + .latitude(spot.getLatitude()) + .longitude(spot.getLongitude()) + //.image(spot.getImage()) + .stars(spot.getStars()) + // .guestbookCount(guestRepository.countBySpotId(spot.getID())) + .isFavorited(spotLiked) + .createdAt(spot.getCreatedAt()) + .build(); + }*/ + + // 전체 조회 + @Transactional + public ResponseEntity getAllPlaces() { + + final long memberId = SecurityUtil.getCurrentMemeberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + List allPlaces = getAllPlaceResList(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(allPlaces) + .build(); + + return ResponseEntity.ok(apiResponse); + } +} diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java new file mode 100644 index 00000000..4ba1422b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -0,0 +1,36 @@ +package com.ttubeog.domain.place.presentation; + +import com.ttubeog.domain.place.application.PlaceService; +import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; +import com.ttubeog.global.payload.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.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "Place", description = "Place API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/place") +public class PlaceController { + + private final PlaceService placeService; + + // 전체 조회 + @Operation(summary = "전체 장소 조회", description = "전체 장소를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "전체 장소 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetAllPlaceRes.class))}), + @ApiResponse(responseCode = "400", description = "전체 장소 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping + public ResponseEntity getAllPlaces() { + return placeService.getAllPlaces(); + } +} From 3eed95f654929ba833d28c318449f6edb050e4ad Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Wed, 7 Feb 2024 23:41:25 +0900 Subject: [PATCH 162/356] =?UTF-8?q?[Feat]=20=EC=9E=A5=EC=86=8C=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=EC=88=9C=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/place/application/PlaceService.java | 17 +++++++++++++++++ .../place/presentation/PlaceController.java | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 3b5163d2..0fb07fd7 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -103,4 +103,21 @@ public ResponseEntity getAllPlaces() { return ResponseEntity.ok(apiResponse); } + + // 최신순 조회 + @Transactional + public ResponseEntity getAllPlacesLatest() { + + final long memberId = SecurityUtil.getCurrentMemeberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + List allPlaces = getAllPlaceResList(); + allPlaces.sort(Comparator.comparing(GetAllPlaceRes::getCreatedAt).reversed()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(allPlaces) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 4ba1422b..5168bd80 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -33,4 +33,15 @@ public class PlaceController { public ResponseEntity getAllPlaces() { return placeService.getAllPlaces(); } + + // 최신순 조회 + @Operation(summary = "전체 장소 최신순 조회", description = "전체 장소를 최신순으로 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "최신순 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetAllPlaceRes.class))}), + @ApiResponse(responseCode = "400", description = "최신순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/latest") + public ResponseEntity getAllPlacesLatest() { + return placeService.getAllPlacesLatest(); + } } From cd56181da47da2654df4ef17e06c7237a3436dfc Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 8 Feb 2024 01:21:21 +0900 Subject: [PATCH 163/356] =?UTF-8?q?[Feat]=20=EC=9E=A5=EC=86=8C=20=EC=B6=94?= =?UTF-8?q?=EC=B2=9C=EC=88=9C=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 55 +++++++++++++++++++ .../place/dto/response/GetAllPlaceRes.java | 10 +++- .../place/presentation/PlaceController.java | 11 ++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 0fb07fd7..6029b30e 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -104,6 +104,61 @@ public ResponseEntity getAllPlaces() { return ResponseEntity.ok(apiResponse); } + public int calculateRecommendationScore(float stars, int guestbookCount, int likesCount) { + + int starsScore = (int) (stars * 20); + int guestbookScore = calculateGuestbookScore(guestbookCount); + int likesScore = calculateLikesStore(likesCount); + int totalScore = starsScore + guestbookScore + likesScore; + + return totalScore; + } + + private int calculateGuestbookScore(int guestbookCount) { + + if (guestbookCount <= 10) { + return 10; + } else if (guestbookCount <= 50) { + return 30; + } else { + return 50; + } + } + + private int calculateLikesStore(int likesCount) { + + if (likesCount <= 100) { + return 10; + } else if (likesCount <= 500) { + return 30; + } else { + return 50; + } + } + + // 추천순 조회 + @Transactional + public ResponseEntity getAllPlacesRecommended() { + + final long memberId = SecurityUtil.getCurrentMemeberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + List allPlaces = getAllPlaceResList(); + + for (GetAllPlaceRes place : allPlaces) { + int recommendationScore = calculateRecommendationScore(place.getStars(), place.getGuestbookCount(), place.getLikesCount()); + place.setRecommendationScore(recommendationScore); + } + + allPlaces.sort(Comparator.comparingInt(GetAllPlaceRes::getRecommendationScore).reversed()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(allPlaces) + .build(); + + return ResponseEntity.ok(apiResponse); + } + // 최신순 조회 @Transactional public ResponseEntity getAllPlacesLatest() { diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index 0074aac3..82c7c5e3 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -37,15 +37,21 @@ public class GetAllPlaceRes { @Schema(description = "방명록 수") private Integer guestbookCount; + @Schema(description = "좋아요 수") + private Integer likesCount; + @Schema(description = "좋아요 여부") private Boolean isFavorited; @Schema(description = "생성 시간") private LocalDateTime createdAt; + @Schema(description = "추천 점수") + private Integer recommendationScore; + @Builder public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Float latitude, Float longitude, - String image, Float stars, Integer guestbookCount, Boolean isFavorited, LocalDateTime createdAt) { + String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, LocalDateTime createdAt, Integer recommendationScore) { this.placeId = placeId; this.placeType = placeType; this.memberId = memberId; @@ -55,7 +61,9 @@ public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String n this.image = image; this.stars = stars; this.guestbookCount = guestbookCount; + this.likesCount = likesCount; this.isFavorited = isFavorited; this.createdAt = createdAt; + this.recommendationScore = recommendationScore; } } diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 5168bd80..039ad5b6 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -34,6 +34,17 @@ public ResponseEntity getAllPlaces() { return placeService.getAllPlaces(); } + // 추천순 조회 + @Operation(summary = "전체 장소 추천순 조회", description = "전체 장소를 추천순으로 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "추천순 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetAllPlaceRes.class))}), + @ApiResponse(responseCode = "400", description = "추천순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/recommended") + public ResponseEntity getAllPlacesRecommended() { + return placeService.getAllPlacesRecommended(); + } + // 최신순 조회 @Operation(summary = "전체 장소 최신순 조회", description = "전체 장소를 최신순으로 조회합니다.") @ApiResponses(value = { From 8c798266b5fce46d494f635b3b929cac18277a39 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 8 Feb 2024 02:53:31 +0900 Subject: [PATCH 164/356] =?UTF-8?q?[Feat]=20=EC=9E=A5=EC=86=8C=20=EA=B1=B0?= =?UTF-8?q?=EB=A6=AC=EC=88=9C=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 43 +++++++++++++++++++ .../place/dto/request/GetNearbyPlaceReq.java | 14 ++++++ .../place/dto/response/GetAllPlaceRes.java | 7 ++- .../place/presentation/PlaceController.java | 16 +++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 6029b30e..06de7866 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.place.domain.PlaceType; +import com.ttubeog.domain.place.dto.request.GetNearbyPlaceReq; import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; @@ -159,6 +160,48 @@ public ResponseEntity getAllPlacesRecommended() { return ResponseEntity.ok(apiResponse); } + private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + double R = 6371; // 지구 반지름 + + double dLat = Math.toRadians(lat2 - lat1); + double dLon = Math.toRadians(lon2 - lon1); + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 단위 km + double distance = R * c * 1000; // 단위 m + + return distance; + } + + // 거리순 조회 + @Transactional + public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq) { + + final long memberId = SecurityUtil.getCurrentMemeberId(); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + List allPlaces = getAllPlaceResList(); + + Float userLatitude = getNearbyPlaceReq.getLatitude(); + Float userLongitude = getNearbyPlaceReq.getLongitude(); + + for (GetAllPlaceRes place: allPlaces) { + double distance = calculateDistance(userLatitude, userLongitude, place.getLatitude(), place.getLongitude()); + place.setDistance(distance); + } + + allPlaces.sort(Comparator.comparingDouble(GetAllPlaceRes::getDistance)); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(allPlaces) + .build(); + + return ResponseEntity.ok(apiResponse); + } + // 최신순 조회 @Transactional public ResponseEntity getAllPlacesLatest() { diff --git a/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java b/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java new file mode 100644 index 00000000..e60849ca --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.place.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetNearbyPlaceReq { + + @Schema(description = "사용자 위치 위도값") + private Float latitude; + + @Schema(description = "사용자 위치 경도값") + private Float longitude; +} diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index 82c7c5e3..928e4f74 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -49,9 +49,13 @@ public class GetAllPlaceRes { @Schema(description = "추천 점수") private Integer recommendationScore; + @Schema(description = "사용자와의 거리") + private Double distance; + @Builder public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Float latitude, Float longitude, - String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, LocalDateTime createdAt, Integer recommendationScore) { + String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, + LocalDateTime createdAt, Integer recommendationScore, Double distance) { this.placeId = placeId; this.placeType = placeType; this.memberId = memberId; @@ -65,5 +69,6 @@ public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String n this.isFavorited = isFavorited; this.createdAt = createdAt; this.recommendationScore = recommendationScore; + this.distance = distance; } } diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 039ad5b6..57a537b5 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.place.presentation; import com.ttubeog.domain.place.application.PlaceService; +import com.ttubeog.domain.place.dto.request.GetNearbyPlaceReq; import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; @@ -9,9 +10,11 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -45,6 +48,19 @@ public ResponseEntity getAllPlacesRecommended() { return placeService.getAllPlacesRecommended(); } + // 거리순 조회 + @Operation(summary = "전체 장소 거리순 조회", description = "전체 장소를 거리순으로 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "거리순 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetAllPlaceRes.class))}), + @ApiResponse(responseCode = "400", description = "거리순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/nearby") + public ResponseEntity getAllPlacesNearby( + @Valid @RequestBody GetNearbyPlaceReq getNearbyPlaceReq + ) { + return placeService.getAllPlacesNearby(getNearbyPlaceReq); + } + // 최신순 조회 @Operation(summary = "전체 장소 최신순 조회", description = "전체 장소를 최신순으로 조회합니다.") @ApiResponses(value = { From e27a740aa3d54f89b4c5cd2b0f8fa2120c498f72 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 18:04:24 +0900 Subject: [PATCH 165/356] [refac] merge with dev --- .../com/ttubeog/domain/spot/application/SpotService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 9c335b1e..7d322268 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; @@ -23,6 +24,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -45,6 +47,8 @@ public class SpotService { private final ImageService imageService; + private final JwtTokenProvider jwtTokenProvider; + @NonNull private ResponseEntity getResponseEntity(Spot spot) { @@ -70,7 +74,9 @@ private ResponseEntity getResponseEntity(Spot spot) { } @Transactional - public ResponseEntity createSpot(UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { + public ResponseEntity createSpot(HttpServletRequest request, UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { + + Long memberId = jwtTokenProvider.getMemberId(request); // 유효한 사용자 로그인 상태인지 체크 Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); From 7096525c74d615f758eaaf1921c727b1ff4b75c1 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 18:08:46 +0900 Subject: [PATCH 166/356] [feat] change user princible to httpserveletrequest --- .../application/GuestBookService.java | 3 ++- .../domain/spot/application/SpotService.java | 24 +++++++++++------- .../spot/presentation/SpotController.java | 25 ++++++++++--------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index d8c1c7b3..56720b5a 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; import com.ttubeog.global.config.security.token.UserPrincipal; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -11,7 +12,7 @@ @Service @Transactional(readOnly = true) public class GuestBookService { - public ResponseEntity createGuestBook(UserPrincipal userPrincipal, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { + public ResponseEntity createGuestBook(HttpServletRequest request, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { return null; } } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 7d322268..9ea2a84e 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -74,12 +74,12 @@ private ResponseEntity getResponseEntity(Spot spot) { } @Transactional - public ResponseEntity createSpot(HttpServletRequest request, UserPrincipal userPrincipal, CreateSpotRequestDto createSpotRequestDto) { + public ResponseEntity createSpot(HttpServletRequest request, CreateSpotRequestDto createSpotRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); // 유효한 사용자 로그인 상태인지 체크 - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 중복된 이름을 가진 산책 스팟인지 체크 if (spotRepository.findByName(createSpotRequestDto.getName()).isPresent()) { @@ -122,10 +122,12 @@ public ResponseEntity createSpot(HttpServletRequest request, UserPrincipal us return getResponseEntity(spot); } - public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Long spotId) { + public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { + + Long memberId = jwtTokenProvider.getMemberId(request); // 유효한 사용자 로그인 상태인지 체크 - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); @@ -133,10 +135,12 @@ public ResponseEntity findBySpotId(UserPrincipal userPrincipal, Long spotId) } @Transactional - public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotRequestDto updateSpotRequestDto) { + public ResponseEntity updateSpot(HttpServletRequest request, UpdateSpotRequestDto updateSpotRequestDto) { + + Long memberId = jwtTokenProvider.getMemberId(request); // 유효한 사용자 로그인 상태인지 체크 - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 존재하는 산책 스팟을 수정하려는지 체크 Spot spot = spotRepository.findById(updateSpotRequestDto.getId()).orElseThrow(InvalidSpotIdException::new); @@ -173,10 +177,12 @@ public ResponseEntity updateSpot(UserPrincipal userPrincipal, UpdateSpotReque } @Transactional - public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { + public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { + + Long memberId = jwtTokenProvider.getMemberId(request); // 유효한 사용자 로그인 상태인지 체크 - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); @@ -196,7 +202,7 @@ public ResponseEntity deleteSpot(UserPrincipal userPrincipal, Long spotId) { } @Transactional - public ResponseEntity likeSpot(UserPrincipal userPrincipal, Integer spotId) { + public ResponseEntity likeSpot(HttpServletRequest request, Integer spotId) { return null; } } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 0b6392e4..f9454181 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -10,6 +10,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -28,55 +29,55 @@ public class SpotController { @PostMapping @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createSpot( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestBody CreateSpotRequestDto createSpotRequestDto ) throws JsonProcessingException { - return spotService.createSpot(userPrincipal, createSpotRequestDto); + return spotService.createSpot(request, createSpotRequestDto); } @Operation(summary = "산책 스팟 세부 사항 조회", description = "산책 스팟의 세부 사항을 조회합니다.") @GetMapping("/{spotId}") public ResponseEntity findBySpotId( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return spotService.findBySpotId(userPrincipal, spotId); + return spotService.findBySpotId(request, spotId); } @Operation(summary = "산책 스팟 수정", description = "산책 스팟에 대한 정보를 수정합니다.") @PatchMapping public ResponseEntity updateSpot( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestBody UpdateSpotRequestDto updateSpotRequestDto ) throws JsonProcessingException { - return spotService.updateSpot(userPrincipal, updateSpotRequestDto); + return spotService.updateSpot(request, updateSpotRequestDto); } @Operation(summary = "산책 스팟 삭제", description = "산책 스팟을 삭제합니다.") @DeleteMapping("/{spotId}") public ResponseEntity deleteSpot( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return spotService.deleteSpot(userPrincipal, spotId); + return spotService.deleteSpot(request, spotId); } @Operation(summary = "산책 스팟 방명록 작성", description = "산책 스팟에 종속된 방명록을 작성합니다.") @PostMapping("/{spotId}/guestbook") public ResponseEntity createGuestBook( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Integer spotId, @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto ) throws JsonProcessingException { - return guestBookService.createGuestBook(userPrincipal, spotId, createGuestBookRequestDto); + return guestBookService.createGuestBook(request, spotId, createGuestBookRequestDto); } @Operation(summary = "산책 스팟 좋아요 누르기", description = "산책 스팟에 좋아요를 누릅니다.") @PatchMapping("/{spotId}/likes") public ResponseEntity likeSpot( - @CurrentUser UserPrincipal userPrincipal, + @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Integer spotId ) throws JsonProcessingException { - return spotService.likeSpot(userPrincipal, spotId); + return spotService.likeSpot(request, spotId); } } From 7e82c454f3e1641358ce9e95df53261d456737e9 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 18:47:08 +0900 Subject: [PATCH 167/356] [refac] refac security config --- .../domain/auth/config/SecurityConfig.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java index 715cc6ba..ead9e8e4 100644 --- a/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java +++ b/src/main/java/com/ttubeog/domain/auth/config/SecurityConfig.java @@ -7,6 +7,7 @@ import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @@ -27,15 +28,20 @@ public AuthenticationManager authenticationManager( @Bean public SecurityFilterChain configure(final HttpSecurity httpSecurity) throws Exception { return httpSecurity.cors(withDefaults()) - .csrf((csrf) -> csrf.disable()) + .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/auth/login/**").permitAll() - .requestMatchers("/swagger-ui/**", "/v3/api-docs", "/swagger-resources/**", "/api/**").permitAll() + .requestMatchers("/swagger-ui/**", + "/v2/api-docs", + "/swagger-resources/**", + "/h2-console/**", + "/favicon.ico", + "/v3/api-docs/**", + "/api/**").permitAll() // .requestMatchers("/api/**").hasAuthority(MemberRole.USER.getRole()) .anyRequest().authenticated()) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable()) // 기본 로그인 폼 미사용 - .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable()) // 기본 http 미사용 + .formLogin(AbstractHttpConfigurer::disable) // 기본 로그인 폼 미사용 + .httpBasic(AbstractHttpConfigurer::disable) // 기본 http 미사용 .build(); } @@ -58,12 +64,13 @@ public boolean matches(CharSequence rawPassword, String encodedPassword) { public WebSecurityCustomizer webSecurityCustomizer(){ return web -> web.ignoring() - .requestMatchers("/auth/login/**") - .requestMatchers("/swagger-ui/**", + .requestMatchers("/auth/login/**", + "/swagger-ui/**", "/v2/api-docs", "/swagger-resources/**", "/h2-console/**", "/favicon.ico", - "/v3/api-docs/**"); + "/v3/api-docs/**", + "/api/**"); } } From 747ee99b70eb195180558d38a01a2000064aec20 Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 8 Feb 2024 21:57:44 +0900 Subject: [PATCH 168/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=EC=8B=9C=20check=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20false=20=EB=B0=98=ED=99=98=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/DuplicatedNicknameException.java | 7 +++++++ .../domain/member/application/MemberService.java | 14 ++++++++++++-- .../member/domain/repository/MemberRepository.java | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java diff --git a/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java b/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java new file mode 100644 index 00000000..93945047 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.auth.exception; + +public class DuplicatedNicknameException extends RuntimeException { + public DuplicatedNicknameException() { + super("중복된 닉네임입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 073d6d20..9912704d 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; +import com.ttubeog.domain.auth.exception.DuplicatedNicknameException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.auth.service.RefreshTokenService; @@ -13,6 +14,7 @@ import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.ErrorResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -52,14 +54,21 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { return ResponseEntity.ok(apiResponse); } - // 닉네임 설정 @Transactional public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); + + if (memberRepository.existsByNickname(produceNicknameRequest.getNickname())) { + ApiResponse apiResponse = ApiResponse.builder() + .check(false) + .build(); + + return ResponseEntity.ok(apiResponse); + } + memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); Optional checkMember = memberRepository.findById(memberId); - Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() @@ -76,6 +85,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } + @Transactional // 토큰 재발급 설정 public ResponseEntity getMemberReissueToken(HttpServletRequest request) { diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index f9889abb..98c94072 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -36,4 +36,6 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") void updateUserNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); + + Boolean existsByNickname(String nickname); } From a361694183f2d96876b93b650aa721c351c56c20 Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 8 Feb 2024 22:00:28 +0900 Subject: [PATCH 169/356] =?UTF-8?q?[Feat]=20controller=20description=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/member/presentation/MemberController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 4fadb718..adb1bd0b 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -36,7 +36,7 @@ public ResponseEntity getCurrentMember( return memberService.getCurrentUser(request); } - @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.") + @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.\ncheck == true 인 경우 닉네임 설정 성공, check == false 인 경우 닉네임 중복으로 실패") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), From 52d07090d362bffb6c565ca4440d92691cbcb411 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 23:20:37 +0900 Subject: [PATCH 170/356] [feat] implement just spot service --- .../member/exception/InvalidMemberException.java | 5 +++++ .../ttubeog/domain/spot/application/SpotService.java | 12 +++++++++--- .../spot/dto/request/UpdateSpotRequestDto.java | 1 - .../spot/exception/InvalidDongAreaException.java | 4 ++++ .../spot/exception/InvalidSpotIdException.java | 4 ++++ .../domain/spot/presentation/SpotController.java | 3 ++- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java index b3c1b113..447f6051 100644 --- a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java +++ b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java @@ -1,9 +1,14 @@ package com.ttubeog.domain.member.exception; +import com.ttubeog.domain.spot.exception.InvalidDongAreaException; + public class InvalidMemberException extends RuntimeException { public InvalidMemberException(){ super("멤버가 올바르지 않습니다."); } + public InvalidMemberException(String message) { + super(message); + } } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 9ea2a84e..999dccad 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -135,7 +135,7 @@ public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { } @Transactional - public ResponseEntity updateSpot(HttpServletRequest request, UpdateSpotRequestDto updateSpotRequestDto) { + public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, UpdateSpotRequestDto updateSpotRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -143,11 +143,14 @@ public ResponseEntity updateSpot(HttpServletRequest request, UpdateSpotReques memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 존재하는 산책 스팟을 수정하려는지 체크 - Spot spot = spotRepository.findById(updateSpotRequestDto.getId()).orElseThrow(InvalidSpotIdException::new); + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); // 수정하려는 이름과 중복된 이름을 가진 산책 스팟이 있는지 if (spotRepository.findByName(updateSpotRequestDto.getName()).isPresent()) { - throw new AlreadyExistsSpotException(); + Spot duplicateSpot = spotRepository.findByName(updateSpotRequestDto.getName()).orElseThrow(InvalidSpotIdException::new); + if (!duplicateSpot.getId().equals(spotId)) { + throw new AlreadyExistsSpotException(); + } } // 수정하려는 지역코드가 유효한지 체크 @@ -162,6 +165,7 @@ public ResponseEntity updateSpot(HttpServletRequest request, UpdateSpotReques spotRepository.save(spot); + /* // 이미지 저장 List imageList = updateSpotRequestDto.getImage(); for (String s : imageList) { @@ -173,6 +177,8 @@ public ResponseEntity updateSpot(HttpServletRequest request, UpdateSpotReques imageService.updateImage(updateImageRequestDto); } + */ + return getResponseEntity(spot); } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 0a8db6b8..ddf2baf3 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -11,7 +11,6 @@ @AllArgsConstructor public class UpdateSpotRequestDto { - private Long id; private String name; private Long dongAreaId; private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java b/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java index 34ec557c..3fd67b4e 100644 --- a/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java +++ b/src/main/java/com/ttubeog/domain/spot/exception/InvalidDongAreaException.java @@ -5,4 +5,8 @@ public class InvalidDongAreaException extends RuntimeException{ public InvalidDongAreaException() { super("유효하지 않은 지역 정보입니다."); } + + public InvalidDongAreaException(String message) { + super(message); + } } diff --git a/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java b/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java index 82b74f54..d9d60b0b 100644 --- a/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java +++ b/src/main/java/com/ttubeog/domain/spot/exception/InvalidSpotIdException.java @@ -5,4 +5,8 @@ public class InvalidSpotIdException extends RuntimeException{ public InvalidSpotIdException() { super("존재하지 않은 산책 스팟 Id 값입니다."); } + + public InvalidSpotIdException(String message) { + super(message); + } } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index f9454181..cd510ba4 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -48,9 +48,10 @@ public ResponseEntity findBySpotId( @PatchMapping public ResponseEntity updateSpot( @CurrentUser HttpServletRequest request, + @RequestParam(name = "spotId") Long spotId, @RequestBody UpdateSpotRequestDto updateSpotRequestDto ) throws JsonProcessingException { - return spotService.updateSpot(request, updateSpotRequestDto); + return spotService.updateSpot(request, spotId, updateSpotRequestDto); } @Operation(summary = "산책 스팟 삭제", description = "산책 스팟을 삭제합니다.") From b11ae2236c855219032c0a5847d444968f604332 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Thu, 8 Feb 2024 23:22:04 +0900 Subject: [PATCH 171/356] =?UTF-8?q?Revert=20"[FEAT]=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84=20=EC=A4=91=EB=B3=B5=20API=20=EA=B5=AC=ED=98=84"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/DuplicatedNicknameException.java | 7 ------- .../domain/member/application/MemberService.java | 14 ++------------ .../member/domain/repository/MemberRepository.java | 2 -- .../member/presentation/MemberController.java | 2 +- 4 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java diff --git a/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java b/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java deleted file mode 100644 index 93945047..00000000 --- a/src/main/java/com/ttubeog/domain/auth/exception/DuplicatedNicknameException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.auth.exception; - -public class DuplicatedNicknameException extends RuntimeException { - public DuplicatedNicknameException() { - super("중복된 닉네임입니다."); - } -} diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 9912704d..073d6d20 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -2,7 +2,6 @@ import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; -import com.ttubeog.domain.auth.exception.DuplicatedNicknameException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.auth.service.RefreshTokenService; @@ -14,7 +13,6 @@ import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; -import com.ttubeog.global.payload.ErrorResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -54,21 +52,14 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { return ResponseEntity.ok(apiResponse); } + // 닉네임 설정 @Transactional public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); - - if (memberRepository.existsByNickname(produceNicknameRequest.getNickname())) { - ApiResponse apiResponse = ApiResponse.builder() - .check(false) - .build(); - - return ResponseEntity.ok(apiResponse); - } - memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); Optional checkMember = memberRepository.findById(memberId); + Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() @@ -85,7 +76,6 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } - @Transactional // 토큰 재발급 설정 public ResponseEntity getMemberReissueToken(HttpServletRequest request) { diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 98c94072..f9889abb 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -36,6 +36,4 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") void updateUserNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); - - Boolean existsByNickname(String nickname); } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index adb1bd0b..4fadb718 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -36,7 +36,7 @@ public ResponseEntity getCurrentMember( return memberService.getCurrentUser(request); } - @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.\ncheck == true 인 경우 닉네임 설정 성공, check == false 인 경우 닉네임 중복으로 실패") + @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), From 0cf029a95f6736cdf8ee04e864a65cd1916814b5 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 23:29:31 +0900 Subject: [PATCH 172/356] =?UTF-8?q?[Feat]=20:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20import=EB=AC=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 999dccad..e899d11a 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -8,7 +8,6 @@ import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.image.dto.request.ImageRequestType; -import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -21,7 +20,6 @@ import com.ttubeog.domain.spot.exception.InvalidDongAreaException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; From e005f9f3379a78a477658c42c616592eef604031 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Thu, 8 Feb 2024 23:29:57 +0900 Subject: [PATCH 173/356] =?UTF-8?q?[Feat]=20:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20import=EB=AC=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/presentation/SpotController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index cd510ba4..027d2e38 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -7,7 +7,6 @@ import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; From 118b340e5fb97102d4d77e5ccf68ae9caa163d6d Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 8 Feb 2024 23:40:18 +0900 Subject: [PATCH 174/356] =?UTF-8?q?[Feat]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20saveTokenInfo=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/auth/service/AuthService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 42916738..98a7e589 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -61,9 +61,11 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { } Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); + validateStatus(memberLoginData.get()); String refreshToken = jwtTokenProvider.createRefreshToken(memberLoginData.get().getId()); redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); + refreshTokenService.saveTokenInfo(memberData.get().getId(), refreshToken, accessToken); String memberName = memberLoginData.get().getNickname(); if (memberName == null || memberName.isEmpty()) { From 447efc52c39bacb9a313b794ada03f67f2ed02c9 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 8 Feb 2024 23:41:27 +0900 Subject: [PATCH 175/356] =?UTF-8?q?[Feat]=20=EC=9E=A5=EC=86=8C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=8E=98=EC=9D=B4=EC=A7=95=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 32 +++++++++++++------ .../place/presentation/PlaceController.java | 32 ++++++++++++------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 06de7866..33483e9f 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -13,6 +13,8 @@ import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -33,7 +35,14 @@ public class PlaceService { private final SpotRepository spotRepository; private final LikesRepository likesRepository; - public List getAllPlaceResList() { + public List getPageOfPlaces(List places, int page, int size) { + int startIndex = page * size; + int endIndex = Math.min(startIndex + size, places.size()); + + return places.subList(startIndex, endIndex); + } + + public List getAllPlaceResList(Pageable pageable) { List places = new ArrayList<>(); @@ -41,8 +50,10 @@ public List getAllPlaceResList() { places.addAll(stores.stream().map(this::mapStoreToDto).collect(Collectors.toList())); // List spots = spotRepository.findAll(); // places.addAll(spots.stream().map(this::mapSpotToDto).collect(Collectors.toList())); + int page = pageable.getPageNumber(); + int size = pageable.getPageSize(); - return places; + return getPageOfPlaces(places, page, size); } private GetAllPlaceRes mapStoreToDto(Store store) { @@ -91,11 +102,12 @@ private GetAllPlaceRes mapStoreToDto(Store store) { // 전체 조회 @Transactional - public ResponseEntity getAllPlaces() { + public ResponseEntity getAllPlaces(Pageable pageable) { final long memberId = SecurityUtil.getCurrentMemeberId(); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(); + + List allPlaces = getAllPlaceResList(pageable); ApiResponse apiResponse = ApiResponse.builder() .check(true) @@ -139,11 +151,11 @@ private int calculateLikesStore(int likesCount) { // 추천순 조회 @Transactional - public ResponseEntity getAllPlacesRecommended() { + public ResponseEntity getAllPlacesRecommended(Pageable pageable) { final long memberId = SecurityUtil.getCurrentMemeberId(); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(); + List allPlaces = getAllPlaceResList(pageable); for (GetAllPlaceRes place : allPlaces) { int recommendationScore = calculateRecommendationScore(place.getStars(), place.getGuestbookCount(), place.getLikesCount()); @@ -178,11 +190,11 @@ private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) // 거리순 조회 @Transactional - public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq) { + public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq, Pageable pageable) { final long memberId = SecurityUtil.getCurrentMemeberId(); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(); + List allPlaces = getAllPlaceResList(pageable); Float userLatitude = getNearbyPlaceReq.getLatitude(); Float userLongitude = getNearbyPlaceReq.getLongitude(); @@ -204,11 +216,11 @@ public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq) // 최신순 조회 @Transactional - public ResponseEntity getAllPlacesLatest() { + public ResponseEntity getAllPlacesLatest(Pageable pageable) { final long memberId = SecurityUtil.getCurrentMemeberId(); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(); + List allPlaces = getAllPlaceResList(pageable); allPlaces.sort(Comparator.comparing(GetAllPlaceRes::getCreatedAt).reversed()); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 57a537b5..57b525b7 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -12,11 +12,10 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "Place", description = "Place API") @RestController @@ -33,8 +32,10 @@ public class PlaceController { @ApiResponse(responseCode = "400", description = "전체 장소 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping - public ResponseEntity getAllPlaces() { - return placeService.getAllPlaces(); + public ResponseEntity getAllPlaces(@RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + return placeService.getAllPlaces(pageable); } // 추천순 조회 @@ -44,8 +45,10 @@ public ResponseEntity getAllPlaces() { @ApiResponse(responseCode = "400", description = "추천순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/recommended") - public ResponseEntity getAllPlacesRecommended() { - return placeService.getAllPlacesRecommended(); + public ResponseEntity getAllPlacesRecommended(@RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + return placeService.getAllPlacesRecommended(pageable); } // 거리순 조회 @@ -56,9 +59,12 @@ public ResponseEntity getAllPlacesRecommended() { }) @GetMapping("/nearby") public ResponseEntity getAllPlacesNearby( - @Valid @RequestBody GetNearbyPlaceReq getNearbyPlaceReq + @Valid @RequestBody GetNearbyPlaceReq getNearbyPlaceReq, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size ) { - return placeService.getAllPlacesNearby(getNearbyPlaceReq); + Pageable pageable = PageRequest.of(page, size); + return placeService.getAllPlacesNearby(getNearbyPlaceReq, pageable); } // 최신순 조회 @@ -68,7 +74,9 @@ public ResponseEntity getAllPlacesNearby( @ApiResponse(responseCode = "400", description = "최신순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/latest") - public ResponseEntity getAllPlacesLatest() { - return placeService.getAllPlacesLatest(); + public ResponseEntity getAllPlacesLatest(@RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + return placeService.getAllPlacesLatest(pageable); } } From 5115b615dff63c4c06264dcc044b3a6389e4f06b Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 9 Feb 2024 00:24:12 +0900 Subject: [PATCH 176/356] [Docs] add swagger annotation --- .../exception/InvalidMemberException.java | 1 - .../com/ttubeog/domain/spot/domain/Spot.java | 11 +- .../dto/request/CreateSpotRequestDto.java | 15 + .../dto/request/UpdateSpotRequestDto.java | 14 + .../spot/dto/response/SpotResponseDto.java | 19 +- .../spot/presentation/SpotController.java | 392 +++++++++++++++++- 6 files changed, 443 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java index 447f6051..fd09e0fb 100644 --- a/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java +++ b/src/main/java/com/ttubeog/domain/member/exception/InvalidMemberException.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.member.exception; -import com.ttubeog.domain.spot.exception.InvalidDongAreaException; public class InvalidMemberException extends RuntimeException { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index fa7430e7..9410b862 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.member.domain.Member; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -26,29 +27,37 @@ public class Spot extends BaseEntity { @Column(nullable = false) private Long id; + @Schema(description = "산책 스팟 이름", example = "서울 성곽 길") @Column(name = "name", nullable = false) private String name; + @Schema(description = "세부 정보", example = "서울 성곽 길은 조선 시대에 건축된 한성 성곽을 따라 조성된 산책로입니다.") @Column(name = "info", nullable = false) private String info; + @Schema(description = "위도", example = "36.5642886") @Column(name = "latitude", nullable = false) private Float latitude; + @Schema(description = "경도", example = "126.9275718") @Column(name = "longitude", nullable = false) private Float longitude; - @Column(name = "starts") + @Schema(description = "별점 평균", example = "3.4") + @Column(name = "stars") private Float stars; + @Schema(description = "등록 유저", example = "Member Entity") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id", nullable = false) private Member member; + @Schema(description = "지역 코드", example = "DongArea Entity") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dong_area_id", nullable = false) private DongArea dongArea; + @Schema(description = "상세 주소", example = "301호") @Column(name = "detail_address", nullable = false) private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 94354f68..4b4089de 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -1,22 +1,37 @@ package com.ttubeog.domain.spot.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import java.util.List; +@Schema(description = "게시글 생성 DTO") @Getter @Builder @AllArgsConstructor public class CreateSpotRequestDto { + @Schema(description = "산책 스팟 이름", defaultValue = "나의 산책 스팟") private String name; + + @Schema(description = "지역 코드 ID", defaultValue = "1") private Long dongAreaId; + + @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; + + @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") private String info; + + @Schema(description = "위도", defaultValue = "36.5642886") private Float latitude; + + @Schema(description = "경도", defaultValue = "126.9275718") private Float longitude; + + @Schema(description = "이미지 리스트") private List image; } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index ddf2baf3..84debe42 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.spot.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -11,12 +12,25 @@ @AllArgsConstructor public class UpdateSpotRequestDto { + @Schema(description = "산책 스팟 이름", defaultValue = "나의 산책 스팟") private String name; + + @Schema(description = "지역 코드 ID", defaultValue = "1") private Long dongAreaId; + + @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; + + @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") private String info; + + @Schema(description = "위도", defaultValue = "36.5642886") private Float latitude; + + @Schema(description = "경도", defaultValue = "126.9275718") private Float longitude; + + @Schema(description = "이미지 리스트") private List image; } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index f4b0629e..a5f69737 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.global.payload.ApiResponse; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -19,15 +20,31 @@ @AllArgsConstructor public class SpotResponseDto { + @Schema(description = "산책 스팟 ID", defaultValue = "1") private Long id; + + @Schema(description = "산책 스팟 이름", defaultValue = "나의 산책 스팟") private String name; - private Long memberId; + + @Schema(description = "지역 코드 ID", defaultValue = "1") private Long dongAreaId; + + @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; + + @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") private String info; + + @Schema(description = "위도", defaultValue = "36.5642886") private Float latitude; + + @Schema(description = "경도", defaultValue = "126.9275718") private Float longitude; + + @Schema(description = "이미지 리스트") private List image; + + @Schema(description = "평균 별점", defaultValue = "4.5") private Float stars; } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 027d2e38..7b4ab26a 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -3,11 +3,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.guestbook.application.GuestBookService; import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.application.SpotService; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.domain.spot.dto.response.SpotResponseDto; +import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; +import com.ttubeog.domain.spot.exception.InvalidDongAreaException; +import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.global.config.security.token.CurrentUser; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +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.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -24,7 +33,69 @@ public class SpotController { private final SpotService spotService; private final GuestBookService guestBookService; - @Operation(summary = "산책 스팟 생성", description = "산책 스팟을 생성합니다.") + + /** + * 산책 스팟 생성 API + * @param request 유저 검증 + * @param createSpotRequestDto 산책 스팟 생성 DTO + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException json processing 에러 + */ + @Operation(summary = "산책 스팟 생성", + description = "산책 스팟을 생성합니다.\n" + + "사진은 1~10장 사이여야 합니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @PostMapping @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createSpot( @@ -34,7 +105,68 @@ public ResponseEntity createSpot( return spotService.createSpot(request, createSpotRequestDto); } - @Operation(summary = "산책 스팟 세부 사항 조회", description = "산책 스팟의 세부 사항을 조회합니다.") + + /** + * 산책 스팟 세부 사항 조회 API + * @param request 유저 검증 + * @param spotId 산책 스팟 ID + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException + */ + @Operation(summary = "산책 스팟 세부 사항 조회 API", + description = "산책 스팟을 세부 조회합니다.\n", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @GetMapping("/{spotId}") public ResponseEntity findBySpotId( @CurrentUser HttpServletRequest request, @@ -43,7 +175,71 @@ public ResponseEntity findBySpotId( return spotService.findBySpotId(request, spotId); } - @Operation(summary = "산책 스팟 수정", description = "산책 스팟에 대한 정보를 수정합니다.") + + /** + * 산책 스팟 수정 API + * @param request 유저 검증 + * @param spotId 산책 스팟 ID + * @param updateSpotRequestDto 산책스팟 업데이트 DTO + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException JSON processing 에러 + */ + @Operation(summary = "산책 스팟 수정 API", + description = "산책 스팟에 대한 정보를 수정해주세요.\n" + + "사진은 1~10장 사이여야 합니다.\n" + + "사진 수정은 아직 수정 중입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @PatchMapping public ResponseEntity updateSpot( @CurrentUser HttpServletRequest request, @@ -53,7 +249,68 @@ public ResponseEntity updateSpot( return spotService.updateSpot(request, spotId, updateSpotRequestDto); } - @Operation(summary = "산책 스팟 삭제", description = "산책 스팟을 삭제합니다.") + /** + * 산책 스팟 삭제 API + * @param request 유저 검증 + * @param spotId 산책 스팟 ID + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException JSON Processing 에러 + */ + @Operation(summary = "산책 스팟 삭제", + description = "산책 스팟을 삭제합니다.\n" + + "산책 스팟 ID를 입력해주세요", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @DeleteMapping("/{spotId}") public ResponseEntity deleteSpot( @CurrentUser HttpServletRequest request, @@ -62,7 +319,70 @@ public ResponseEntity deleteSpot( return spotService.deleteSpot(request, spotId); } - @Operation(summary = "산책 스팟 방명록 작성", description = "산책 스팟에 종속된 방명록을 작성합니다.") + + /** + * 산책 스팟 방명록 작성 API + * @param request 유저 검증 + * @param spotId 산책 스팟 ID + * @param createGuestBookRequestDto 방명록 작성 DTO + * @return ResponseEntity -> GuestBookResponseDto + * @throws JsonProcessingException JSON Processing 에러 + */ + @Operation(summary = "산책 스팟 방명록 작성", + description = "산책 스팟을 방명록을 작성합니다.\n" + + "GuestBook(방명록) 기능 미구현.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @PostMapping("/{spotId}/guestbook") public ResponseEntity createGuestBook( @CurrentUser HttpServletRequest request, @@ -72,7 +392,67 @@ public ResponseEntity createGuestBook( return guestBookService.createGuestBook(request, spotId, createGuestBookRequestDto); } - @Operation(summary = "산책 스팟 좋아요 누르기", description = "산책 스팟에 좋아요를 누릅니다.") + /** + * 산책 스팟 좋아요 누르기 API + * @param request 유저 검증 + * @param spotId 산책 스팟 ID + * @return ResponseEntity + * @throws JsonProcessingException JSON Processing 에러 + */ + @Operation(summary = "산책 스팟 좋아요 누르기", + description = "산책 스팟에 좋아요를 누릅니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidImageListSizeException", + description = "유효하지 않은 이미지 개수입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) + ) + } + ) + } + ) @PatchMapping("/{spotId}/likes") public ResponseEntity likeSpot( @CurrentUser HttpServletRequest request, From fb9b3e53c10bacc8d99a4933208bde3eee966d22 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 9 Feb 2024 00:27:17 +0900 Subject: [PATCH 177/356] [Docs] add swagger annotation2 --- .../com/ttubeog/domain/spot/dto/response/SpotResponseDto.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index a5f69737..87253f5c 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -32,6 +32,9 @@ public class SpotResponseDto { @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; + @Schema(description = "등록 유저 ID", defaultValue = "1") + private Long memberId; + @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") private String info; From 784352fdf61dd791ffba7c30358f794417fee224 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 9 Feb 2024 00:31:40 +0900 Subject: [PATCH 178/356] =?UTF-8?q?[Refac]=20unuse=20import=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/spot/dto/response/SpotResponseDto.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 87253f5c..794d5d01 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -1,19 +1,13 @@ package com.ttubeog.domain.spot.dto.response; -import com.ttubeog.domain.image.application.ImageService; -import com.ttubeog.domain.spot.domain.Spot; -import com.ttubeog.global.payload.ApiResponse; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import lombok.NonNull; -import org.springframework.http.ResponseEntity; import java.util.List; -import static com.ttubeog.domain.image.application.ImageService.getImageString; @Getter @Builder From 72dc67f6dcd896814a4e024ab67310f3c8b04f46 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:59:21 +0900 Subject: [PATCH 179/356] Update gradle.yml --- .github/workflows/gradle.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f4a04caf..04e3f9de 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -88,24 +88,24 @@ jobs: path: | build/libs/*.jar - - name: Remove past EC2 raw sorce dir - uses: appleboy/ssh-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - command: sudo rm -rf /home/ubuntu/app/code - port: 22 +# - name: Remove past EC2 raw sorce dir +# uses: appleboy/ssh-action@master +# with: +# key: ${{ secrets.EC2_KEY }} +# host: ${{ secrets.EC2_HOST }} +# username: ${{ secrets.EC2_USER }} +# command: sudo rm -rf /home/ubuntu/app/code +# port: 22 - - name: Upload raw sorce to EC2 - uses: appleboy/scp-action@master - with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - source: . - target: "/home/ubuntu/app/code" +# - name: Upload raw sorce to EC2 +# uses: appleboy/scp-action@master +# with: +# key: ${{ secrets.EC2_KEY }} +# host: ${{ secrets.EC2_HOST }} +# username: ${{ secrets.EC2_USER }} +# source: . +# target: "/home/ubuntu/app/code" - name: Start redis-server uses: appleboy/scp-action@master From bafd8f79da4d72d38a4c0875cf6451433498b6fd Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 01:06:24 +0900 Subject: [PATCH 180/356] =?UTF-8?q?[Chore]=20Comment=20=ED=98=84=EC=9E=AC?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=20=ED=99=95=EC=9D=B8=20=EB=B0=A9=EB=B2=95?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 18 ++++++++++++------ .../presentation/CommentController.java | 13 +++++++------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 1773b996..6b173662 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.comment.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; import com.ttubeog.domain.comment.dto.request.GetCommentReq; @@ -17,6 +18,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -34,12 +36,14 @@ public class CommentService { private final CommentRepository commentRepository; private final MemberRepository memberRepository; + private final JwtTokenProvider jwtTokenProvider; // 댓글 작성 @Transactional - public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentReq writeCommentReq) { + public ResponseEntity writeComment(HttpServletRequest request, WriteCommentReq writeCommentReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = Comment.builder() .content(writeCommentReq.getContent()) @@ -68,9 +72,10 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentR // 댓글 수정 @Transactional - public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommentReq updateCommentReq) { + public ResponseEntity updateComment(HttpServletRequest request, UpdateCommentReq updateCommentReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = commentRepository.findById(updateCommentReq.getCommentId()).orElseThrow(NonExistentCommentException::new); Member commentWriter = comment.getMember(); @@ -95,9 +100,10 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommen // 댓글 삭제 @Transactional - public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { + public ResponseEntity deleteComment(HttpServletRequest request, Long commentId) { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = commentRepository.findById(commentId).orElseThrow(NonExistentCommentException::new); commentRepository.delete(comment); diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index f214e68a..ac7adb7f 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -40,10 +41,10 @@ public class CommentController { }) @PostMapping public ResponseEntity writeComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody WriteCommentReq writeCommentReq ) { - return commentService.writeComment(userPrincipal, writeCommentReq); + return commentService.writeComment(request, writeCommentReq); } // 댓글 수정 @@ -54,10 +55,10 @@ public ResponseEntity writeComment( }) @PatchMapping public ResponseEntity updateComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateCommentReq updateCommentReq ) { - return commentService.updateComment(userPrincipal, updateCommentReq); + return commentService.updateComment(request, updateCommentReq); } // 댓글 삭제 @@ -68,10 +69,10 @@ public ResponseEntity updateComment( }) @DeleteMapping("/{commentId}") public ResponseEntity deleteComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable Long commentId ) { - return commentService.deleteComment(userPrincipal, commentId); + return commentService.deleteComment(request, commentId); } // AR뷰 댓글 조회 (반경 이용) From d0188e45c2b116c1cb7bae42cef32dba911a19a8 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 04:07:05 +0900 Subject: [PATCH 181/356] =?UTF-8?q?[Fix]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=A4=91=EB=B3=B5=20=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/security/JwtTokenProvider.java | 5 +-- .../domain/auth/service/AuthService.java | 31 +++++++++---------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java index 4c280527..7d22715c 100644 --- a/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java +++ b/src/main/java/com/ttubeog/domain/auth/security/JwtTokenProvider.java @@ -29,13 +29,10 @@ public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey, } public String createAccessToken(Long memberId) { - Claims claims = Jwts.claims().setSubject(String.valueOf(memberId)); - Date now = new Date(); Date validity = new Date(now.getTime() + validityAccessTokenInMilliseconds); return Jwts.builder() - .setClaims(claims) .setSubject(String.valueOf(memberId)) .setIssuedAt(now) .setExpiration(validity) @@ -70,7 +67,7 @@ public void validateAccessToken(String token) { } } - private boolean isExpiredAccessToken (String token) { + public boolean isExpiredAccessToken (String token) { try { jwtParser.parseClaimsJws(token); } catch (ExpiredJwtException e) { diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 98a7e589..82a662af 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -8,7 +8,6 @@ import com.ttubeog.domain.auth.dto.request.AppleLoginRequest; import com.ttubeog.domain.auth.dto.response.KakaoTokenResponse; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; -import com.ttubeog.domain.auth.exception.NotFoundMemberException; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.auth.security.OAuthPlatformMemberResponse; import com.ttubeog.domain.member.domain.Member; @@ -18,6 +17,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.reactive.function.client.WebClient; import java.util.Optional; @@ -33,6 +33,8 @@ public class AuthService { private final RedisTemplate redisTemplate; + + @Transactional public OAuthTokenResponse appleOAuthLogin(AppleLoginRequest request) { OAuthPlatformMemberResponse applePlatformMember = appleOAuthMemberProvider.getApplePlatformMember(request.getToken()); @@ -86,33 +88,27 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { } private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String email, String platformId) { - return memberRepository.findIdByPlatformAndPlatformId(platform, platformId) - .map(memberId -> { - Member findMember = memberRepository.findById(memberId) - .orElseThrow(NotFoundMemberException::new); - validateStatus(findMember); - String accessToken = issueAccessToken(findMember); + return memberRepository.findByMemberNumber(platformId) + .map(existingMember -> { + // 이미 가입된 회원인 경우 + validateStatus(existingMember); + String accessToken = issueAccessToken(existingMember); String refreshToken = issueRefreshToken(); - - refreshTokenService.saveTokenInfo(findMember.getId(), refreshToken, accessToken); - - if (!findMember.isRegisteredOAuthMember()) { - return new OAuthTokenResponse(accessToken, refreshToken, false); - } + refreshTokenService.saveTokenInfo(existingMember.getId(), refreshToken, accessToken); return new OAuthTokenResponse(accessToken, refreshToken, true); }) .orElseGet(() -> { - Member oauthMember = new Member(email, platform, Status.ACTIVE, ""); - Member savedMember = memberRepository.save(oauthMember); + // 새로운 회원인 경우 + Member newMember = new Member(email, platform, Status.ACTIVE, platformId); + Member savedMember = memberRepository.save(newMember); String accessToken = issueAccessToken(savedMember); String refreshToken = issueRefreshToken(); - refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); - return new OAuthTokenResponse(accessToken, refreshToken, false); }); } + private String issueAccessToken(final Member findMember) { return jwtTokenProvider.createAccessToken(findMember.getId()); } @@ -138,3 +134,4 @@ public KakaoInfoDto getKakaoUserInfo(String accessToken) { .block(); } } + From 4fba571af3a3dd18ee0e77461fcbcb82a113d4e7 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 04:18:55 +0900 Subject: [PATCH 182/356] =?UTF-8?q?[Fix]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=205?= =?UTF-8?q?00=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/auth/service/AuthService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 82a662af..be2483dc 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -57,20 +57,21 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { member = Member.builder() .memberNumber(String.valueOf(memberInfo.getId())) .platform(Platform.KAKAO) + .status(Status.ACTIVE) .build(); memberRepository.save(member); } Optional memberLoginData = memberRepository.findByMemberNumber(String.valueOf(memberInfo.getId())); - validateStatus(memberLoginData.get()); String refreshToken = jwtTokenProvider.createRefreshToken(memberLoginData.get().getId()); redisTemplate.opsForValue().set(String.valueOf(memberLoginData.get().getId()), refreshToken); - refreshTokenService.saveTokenInfo(memberData.get().getId(), refreshToken, accessToken); String memberName = memberLoginData.get().getNickname(); if (memberName == null || memberName.isEmpty()) { + validateStatus(memberLoginData.get()); + return KakaoTokenResponse.builder() .accessToken(jwtTokenProvider.createAccessToken( memberLoginData.get().getId())) @@ -78,6 +79,8 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { .isRegistered(false) .build(); } else { + validateStatus(memberLoginData.get()); + return KakaoTokenResponse.builder() .accessToken(jwtTokenProvider.createAccessToken( memberLoginData.get().getId())) @@ -90,7 +93,6 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String email, String platformId) { return memberRepository.findByMemberNumber(platformId) .map(existingMember -> { - // 이미 가입된 회원인 경우 validateStatus(existingMember); String accessToken = issueAccessToken(existingMember); String refreshToken = issueRefreshToken(); @@ -98,7 +100,6 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String return new OAuthTokenResponse(accessToken, refreshToken, true); }) .orElseGet(() -> { - // 새로운 회원인 경우 Member newMember = new Member(email, platform, Status.ACTIVE, platformId); Member savedMember = memberRepository.save(newMember); String accessToken = issueAccessToken(savedMember); From 6a6a2aa3bbfbfda4a483e0407775d2305971da97 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 04:25:47 +0900 Subject: [PATCH 183/356] =?UTF-8?q?[Feat]=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 4fadb718..0837af0b 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.global.payload.ErrorResponse; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -60,4 +61,16 @@ public ResponseEntity loginReissue( return memberService.getMemberReissueToken(request); } + + @Operation(summary = "로그아웃", description = "현재 접속된 멤버가 로그아웃 합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "로그아웃 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "로그아웃 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @GetMapping("/logout") + public ResponseEntity logout( + HttpServletRequest request + ) { + return null; + } } From 7d4c85b14f715751a2bf06e723c31159d23b6318 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 04:26:50 +0900 Subject: [PATCH 184/356] =?UTF-8?q?[Fix]=20=EB=8C=93=EA=B8=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20Query=20Parameters=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/presentation/CommentController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index ac7adb7f..351b769c 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.global.config.security.token.CurrentUser; @@ -78,12 +79,12 @@ public ResponseEntity deleteComment( // AR뷰 댓글 조회 (반경 이용) @Operation(summary = "댓글 조회", description = "반경 내의 댓글을 조회힙니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = List.class))}), + @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetCommentRes.class))}), @ApiResponse(responseCode = "400", description = "댓글 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping public ResponseEntity getCommentForAR( - @Valid @RequestBody GetCommentReq getCommentReq + @Valid GetCommentReq getCommentReq ) { return commentService.getCommentForAR(getCommentReq); } From 14fbe6cf390ea0c20532913a26e52e94ab1ffc56 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 04:36:07 +0900 Subject: [PATCH 185/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/comment/application/CommentService.java | 4 ---- .../domain/comment/presentation/CommentController.java | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 6b173662..276b17d4 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -14,8 +14,6 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; @@ -26,8 +24,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; - @RequiredArgsConstructor @Service diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index 351b769c..b6b6e7e3 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -7,12 +7,9 @@ import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -24,8 +21,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - @Tag(name = "Comment", description = "Comment API") @RestController @RequiredArgsConstructor From 62779dd7424d34599e8a872a5bf4e275e80c14f7 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 04:41:11 +0900 Subject: [PATCH 186/356] =?UTF-8?q?[Feat]=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 21 +++++++++++++++++++ .../member/presentation/MemberController.java | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 073d6d20..b13039de 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -13,8 +13,10 @@ import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,6 +30,7 @@ public class MemberService { private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenService refreshTokenService; + private final RedisTemplate redisTemplate; // 현재 유저 조회 @@ -113,4 +116,22 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { return ResponseEntity.badRequest().body(new InvalidAccessTokenExpiredException()); } } + + @Transactional + // 로그아웃 + public ResponseEntity deleteLogout(HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberId(request); + deleteValueByKey(String.valueOf(memberId)); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("성공적으로 로그아웃 되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + public void deleteValueByKey(String key) { + redisTemplate.delete(key); + } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 0837af0b..5d20749b 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -67,10 +67,10 @@ public ResponseEntity loginReissue( @ApiResponse(responseCode = "200", description = "로그아웃 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @ApiResponse(responseCode = "400", description = "로그아웃 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) - @GetMapping("/logout") + @DeleteMapping("/logout") public ResponseEntity logout( HttpServletRequest request ) { - return null; + return memberService.deleteLogout(request); } } From 5e605bdb4635fc8a933f65e24614e2a1a7d0937a Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 21 Jan 2024 13:48:45 +0900 Subject: [PATCH 187/356] =?UTF-8?q?[Feat]=20Comment=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 63 ++++++++++++++++++- .../comment/dto/request/GetCommentReq.java | 15 +++++ .../comment/dto/response/GetCommentRes.java | 30 +++++++++ .../presentation/CommentController.java | 28 ++++++--- 4 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java create mode 100644 src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 367e2fef..150d0a43 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -2,8 +2,10 @@ import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; +import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.domain.member.domain.Member; @@ -13,12 +15,17 @@ import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; +import org.apache.catalina.User; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import static java.lang.Math.abs; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -111,6 +118,60 @@ public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long comment return ResponseEntity.ok(apiResponse); } - // 댓글 조회 + public List getAllComments() { + return commentRepository.findAll(); + } + + // AR뷰를 위한 댓글 조회 + public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { + + Float userLatitude = getCommentReq.getLatitude(); + Float userLongitude = getCommentReq.getLongitude(); + + List allComments = getAllComments(); + Double radius = 20.0; // 반경값 확인 필요 + List showComments = new ArrayList<>(); + + for (Comment comment : allComments) { + Float commentLatitude = comment.getLatitude(); + Float commentLongitude = comment.getLongitude(); + + double distance = calculateDistance(userLatitude, userLongitude, commentLatitude, commentLongitude); + + if (distance < radius) { + GetCommentRes getCommentRes = GetCommentRes.builder() + .commentId(comment.getId()) + .memberId(comment.getMember().getId()) + .content(comment.getContent()) + .distance(distance) + .build(); + + showComments.add(getCommentRes); + } + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(showComments) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + // 거리 계산 + private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + double R = 6371; // 지구 반지름 + + double dLat = Math.toRadians(lat2 - lat1); + double dLon = Math.toRadians(lon2 - lon1); + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 단위 km + + return R * c; + } } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java new file mode 100644 index 00000000..5c16e981 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.comment.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class GetCommentReq { + + @Schema(description = "사용자 위치 위도값") + private Float latitude; + + @Schema(description = "사용자 위치 경도값") + private Float longitude; + +} diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java new file mode 100644 index 00000000..e4c7ca9e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/GetCommentRes.java @@ -0,0 +1,30 @@ +package com.ttubeog.domain.comment.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class GetCommentRes { + + @Schema(description = "댓글 ID") + private Long commentId; + + @Schema(description = "작성자 ID") + private Long memberId; + + @Schema(description = "내용") + private String content; + + @Schema(description = "사용자와 해당 댓글 간 거리") + private Double distance; + + @Builder + public GetCommentRes(Long commentId, Long memberId, String content, Double distance) { + this.commentId = commentId; + this.memberId = memberId; + this.content = content; + this.distance = distance; + } + +} diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index cfd84fef..f214e68a 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.comment.presentation; import com.ttubeog.domain.comment.application.CommentService; +import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; @@ -21,6 +22,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + @Tag(name = "Comment", description = "Comment API") @RestController @RequiredArgsConstructor @@ -32,8 +35,8 @@ public class CommentController { // 댓글 작성 @Operation(summary = "댓글 작성", description = "댓글을 작성합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = WriteCommentRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 작성 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = WriteCommentRes.class))}), + @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping public ResponseEntity writeComment( @@ -46,8 +49,8 @@ public ResponseEntity writeComment( // 댓글 수정 @Operation(summary = "댓글 수정", description = "댓글 내용을 수정합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateCommentRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateCommentRes.class))}), + @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PatchMapping public ResponseEntity updateComment( @@ -60,8 +63,8 @@ public ResponseEntity updateComment( // 댓글 삭제 @Operation(summary = "댓글 삭제", description = "댓글을 삭제합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), - @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ) + @ApiResponse(responseCode = "200", description = "댓글 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @DeleteMapping("/{commentId}") public ResponseEntity deleteComment( @@ -71,5 +74,16 @@ public ResponseEntity deleteComment( return commentService.deleteComment(userPrincipal, commentId); } - // 댓글 조회 + // AR뷰 댓글 조회 (반경 이용) + @Operation(summary = "댓글 조회", description = "반경 내의 댓글을 조회힙니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = List.class))}), + @ApiResponse(responseCode = "400", description = "댓글 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping + public ResponseEntity getCommentForAR( + @Valid @RequestBody GetCommentReq getCommentReq + ) { + return commentService.getCommentForAR(getCommentReq); + } } From 80023d2ab277b6cb2914ba5e1ea096e5cebd3a91 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 22 Jan 2024 03:10:23 +0900 Subject: [PATCH 188/356] =?UTF-8?q?[Refac]=20Exception=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 31 +++++++------------ .../NonExistentCommentException.java | 8 +++++ .../UnauthorizedMemberException.java | 8 +++++ 3 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java create mode 100644 src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 150d0a43..1773b996 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -8,14 +8,16 @@ import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; +import com.ttubeog.domain.comment.exception.NonExistentCommentException; +import com.ttubeog.domain.comment.exception.UnauthorizedMemberException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; -import org.apache.catalina.User; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,7 +26,6 @@ import java.util.List; import java.util.Optional; -import static java.lang.Math.abs; @RequiredArgsConstructor @Service @@ -38,9 +39,7 @@ public class CommentService { @Transactional public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentReq writeCommentReq) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - Member member = memberOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); Comment comment = Comment.builder() .content(writeCommentReq.getContent()) @@ -71,19 +70,16 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentR @Transactional public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommentReq updateCommentReq) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional commentOptional = commentRepository.findById(updateCommentReq.getCommentId()); - DefaultAssert.isOptionalPresent(commentOptional); - Comment comment = commentOptional.get(); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Comment comment = commentRepository.findById(updateCommentReq.getCommentId()).orElseThrow(NonExistentCommentException::new); Member commentWriter = comment.getMember(); - if (commentWriter.getId() != memberOptional.get().getId()) { - DefaultAssert.isTrue(true, "해당 댓글의 작성자만 수정할 수 있습니다."); + if (commentWriter.getId() != member.getId()) { + throw new UnauthorizedMemberException(); } comment.updateContent(updateCommentReq.getContent()); + UpdateCommentRes updateCommentRes = UpdateCommentRes.builder() .commentId(comment.getId()) .content(comment.getContent()) @@ -101,13 +97,8 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommen @Transactional public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { - Optional memberOptional = memberRepository.findById(userPrincipal.getId()); - DefaultAssert.isOptionalPresent(memberOptional); - - Optional commentOptional = commentRepository.findById(commentId); - DefaultAssert.isOptionalPresent(commentOptional); - Comment comment = commentOptional.get(); - + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Comment comment = commentRepository.findById(commentId).orElseThrow(NonExistentCommentException::new); commentRepository.delete(comment); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java b/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java new file mode 100644 index 00000000..07a54438 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/exception/NonExistentCommentException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.comment.exception; + +public class NonExistentCommentException extends RuntimeException { + + public NonExistentCommentException() { + super("존재하지 않는 댓글입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java b/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java new file mode 100644 index 00000000..1f4911df --- /dev/null +++ b/src/main/java/com/ttubeog/domain/comment/exception/UnauthorizedMemberException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.comment.exception; + +public class UnauthorizedMemberException extends RuntimeException { + + public UnauthorizedMemberException() { + super("해당 댓글의 작성자가 아닙니다."); + } +} From a4059badb482937920f28bdcf0007e145e189235 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 23 Jan 2024 16:40:53 +0900 Subject: [PATCH 189/356] =?UTF-8?q?[Feat]=20Store=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/store/domain/Store.java | 49 ++++++++++++++++--- .../domain/store/domain/StoreType.java | 5 ++ 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/domain/StoreType.java diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index d143bd6e..dd80d139 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -1,18 +1,55 @@ package com.ttubeog.domain.store.domain; +import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.Getter; +import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.*; +import lombok.*; + +import java.util.List; -@Getter @Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Table(name = "store") public class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "name") + private String name; + + @Column(name = "info") + private String info; + + @Column(name = "detailAddress") + private String detailAddress; + + @Column(name = "latitude") + private Float latitude; + + @Column(name = "longitude") + private Float longitude; + + @Column(name = "image") + private String image; + + @Column(name = "stars") + private Float stars; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private StoreType type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dong_area_id") + private DongArea dongArea; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; } diff --git a/src/main/java/com/ttubeog/domain/store/domain/StoreType.java b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java new file mode 100644 index 00000000..cb90e878 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java @@ -0,0 +1,5 @@ +package com.ttubeog.domain.store.domain; + +public enum StoreType { + restaurant, cafe +} From 35a22bb8126822df392a07e509a952ef87208ca8 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:11:34 +0900 Subject: [PATCH 190/356] =?UTF-8?q?[Feat]=20Store=20=EB=93=B1=EB=A1=9D=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 --- .../ttubeog/domain/area/domain/DongArea.java | 15 +++-- .../store/application/StoreService.java | 55 ++++++++++++++++++ .../store/dto/request/RegisterStoreReq.java | 34 +++++++++++ .../store/dto/response/RegisterStoreRes.java | 56 +++++++++++++++++++ .../store/presentation/StoreController.java | 38 ++++++++++++- 5 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java index 5054c28e..77f27a11 100644 --- a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java +++ b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java @@ -1,17 +1,22 @@ package com.ttubeog.domain.area.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; -@Getter @Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "dong_area") public class DongArea extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + public DongArea(Long id) { + this.id = id; + } } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 7dec1608..0f9ffffb 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -1,6 +1,17 @@ package com.ttubeog.domain.store.application; +import com.ttubeog.domain.area.domain.DongArea; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.global.payload.ApiResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +19,48 @@ @Service @Transactional(readOnly = true) public class StoreService { + + private final StoreRepository storeRepository; + private final MemberRepository memberRepository; + + // 매장 등록 + @Transactional + public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStoreReq registerStoreReq) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + + Store store = Store.builder() + .name(registerStoreReq.getName()) + .info(registerStoreReq.getInfo()) + .dongArea(new DongArea(registerStoreReq.getDongAreaId())) + .detailAddress(registerStoreReq.getDetailAddress()) + .latitude(registerStoreReq.getLatitude()) + .longitude(registerStoreReq.getLongitude()) + .image(registerStoreReq.getImage()) + .type(registerStoreReq.getType()) + .build(); + + storeRepository.save(store); + + RegisterStoreRes registerStoreRes = RegisterStoreRes.builder() + .storeId(store.getId()) + .memberId(member.getId()) + .name(store.getName()) + .info(store.getInfo()) + .dongAreaId(store.getDongArea().getId()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .type(store.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(registerStoreRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java new file mode 100644 index 00000000..e7f8ca18 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java @@ -0,0 +1,34 @@ +package com.ttubeog.domain.store.dto.request; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "매장 등록 Request") +public class RegisterStoreReq { + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; +} diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java new file mode 100644 index 00000000..622a8660 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -0,0 +1,56 @@ +package com.ttubeog.domain.store.dto.response; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +@Schema(description = "매장 등록 Response") +public class RegisterStoreRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "등록 유저 ID") + private Long memberId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; + + @Builder + public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, + String detailAddress,Float latitude, Float longitude, String image, StoreType type) { + this.storeId = storeId; + this.memberId = memberId; + this.name = name; + this.info = info; + this.dongAreaId = dongAreaId; + this.detailAddress = detailAddress; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.type = type; + } +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 01617b11..e9f554a5 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,7 +1,43 @@ package com.ttubeog.domain.store.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.ttubeog.domain.store.application.StoreService; +import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.ErrorResponse; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Store", description = "Store API") @RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/store") public class StoreController { + + private final StoreService storeService; + + // 매장 등록 + @Operation(summary = "매장 등록", description = "매장을 등록합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 등록 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = RegisterStoreRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 등록 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping + public ResponseEntity registerStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody RegisterStoreReq registerStoreReq + ) { + return storeService.registerStore(userPrincipal, registerStoreReq); + } + } From 71af358b07ffbfc05957d33f1fd01d6f2b03dacb Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:15:05 +0900 Subject: [PATCH 191/356] =?UTF-8?q?[Feat]=20Store=20=EC=88=98=EC=A0=95=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 --- .../store/application/StoreService.java | 42 +++++++++++++++++ .../ttubeog/domain/store/domain/Store.java | 28 +++++++++++ .../store/dto/request/UpdateStoreReq.java | 33 +++++++++++++ .../store/dto/response/UpdateStoreRes.java | 46 +++++++++++++++++++ .../exception/NonExistentStoreException.java | 8 ++++ .../exception/UnathorizedMemberException.java | 8 ++++ .../store/presentation/StoreController.java | 15 ++++++ 7 files changed, 180 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java create mode 100644 src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java create mode 100644 src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 0f9ffffb..a08049d2 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -6,7 +6,11 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.request.UpdateStoreReq; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.domain.store.dto.response.UpdateStoreRes; +import com.ttubeog.domain.store.exception.UnathorizedMemberException; +import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; @@ -63,4 +67,42 @@ public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStor return ResponseEntity.ok(apiResponse); } + // 매장 수정 + @Transactional + public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq updateStoreReq) { + + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(updateStoreReq.getStoreId()).orElseThrow(NonExistentStoreException::new); + + Member storeOwner = store.getMember(); + if (storeOwner.getId() != member.getId()) { + throw new UnathorizedMemberException(); + } + + store.updateName(updateStoreReq.getName()); + store.updateInfo(updateStoreReq.getInfo()); + store.updateDetailAddress(updateStoreReq.getDetailAddress()); + store.updateLatitude(updateStoreReq.getLatitude()); + store.updateLongitude(updateStoreReq.getLongitude()); + store.updateImage(updateStoreReq.getImage()); + store.updateType(updateStoreReq.getType()); + + UpdateStoreRes updateStoreRes = UpdateStoreRes.builder() + .storeId(store.getId()) + .name(store.getName()) + .info(store.getInfo()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .type(store.getType()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(updateStoreRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index dd80d139..e1c9b5a1 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -52,4 +52,32 @@ public class Store extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; + + public void updateName(String name) { + this.name = name; + } + + public void updateInfo(String info) { + this.info = info; + } + + public void updateDetailAddress(String detailAddress) { + this.detailAddress = detailAddress; + } + + public void updateLatitude(Float latitude) { + this.latitude = latitude; + } + + public void updateLongitude(Float longitude) { + this.longitude = longitude; + } + + public void updateImage(String image) { + this.image = image; + } + + public void updateType(StoreType type) { + this.type = type; + } } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java new file mode 100644 index 00000000..40e5bdba --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java @@ -0,0 +1,33 @@ +package com.ttubeog.domain.store.dto.request; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UpdateStoreReq { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "상세주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; +} diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java new file mode 100644 index 00000000..1b557760 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -0,0 +1,46 @@ +package com.ttubeog.domain.store.dto.response; + +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + +public class UpdateStoreRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "상세주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "업종") + private StoreType type; + + @Builder + public UpdateStoreRes(Long storeId, String detailAddress, String name, String info, + Float latitude, Float longitude, String image, StoreType type) { + this.storeId = storeId; + this.detailAddress = detailAddress; + this.name = name; + this.info = info; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.type = type; + } +} + diff --git a/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java b/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java new file mode 100644 index 00000000..aafdf330 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/NonExistentStoreException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class NonExistentStoreException extends RuntimeException { + + public NonExistentStoreException() { + super("존재하지 않는 매장입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java new file mode 100644 index 00000000..645d6234 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class UnathorizedMemberException extends RuntimeException { + + public UnathorizedMemberException() { + super("해당 매장에 대한 수정 권한이 없습니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index e9f554a5..8ad34726 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -2,7 +2,9 @@ import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; +import com.ttubeog.domain.store.dto.request.UpdateStoreReq; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; +import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; @@ -40,4 +42,17 @@ public ResponseEntity registerStore( return storeService.registerStore(userPrincipal, registerStoreReq); } + // 매장 수정 + @Operation(summary = "매장 수정", description = "매장 정보를 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateStoreRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PatchMapping + public ResponseEntity updateStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @Valid @RequestBody UpdateStoreReq updateStoreReq + ) { + return storeService.updateStore(userPrincipal, updateStoreReq); + } } From 7c1c3289afc268c97c9f09fecb0ca5aeebb39fb6 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 25 Jan 2024 23:41:48 +0900 Subject: [PATCH 192/356] =?UTF-8?q?[Feat]=20Store=20=EC=82=AD=EC=A0=9C=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 --- .../domain/store/application/StoreService.java | 17 +++++++++++++++++ .../store/presentation/StoreController.java | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index a08049d2..6ef58de3 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -14,6 +14,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -105,4 +106,20 @@ public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq return ResponseEntity.ok(apiResponse); } + + // 매장 삭제 + @Transactional + public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + storeRepository.delete(store); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 8ad34726..f856a1fc 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -55,4 +56,18 @@ public ResponseEntity updateStore( ) { return storeService.updateStore(userPrincipal, updateStoreReq); } + + // 매장 삭제 + @Operation(summary = "매장 삭제", description = "매장 정보를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "매장 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @DeleteMapping("/{storeId}") + public ResponseEntity deleteStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @PathVariable Long storeId + ) { + return storeService.deleteStore(userPrincipal, storeId); + } } From cf5a4c549acd969b8c88912758ad8f50dd2357f4 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Wed, 31 Jan 2024 12:57:01 +0900 Subject: [PATCH 193/356] =?UTF-8?q?[Feat]=20Store=20=EC=84=B8=EB=B6=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/application/StoreService.java | 35 +++++++++++ .../store/dto/response/GetStoreDetailRes.java | 58 +++++++++++++++++++ .../store/presentation/StoreController.java | 14 +++++ 3 files changed, 107 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 6ef58de3..30518659 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; import com.ttubeog.domain.store.dto.request.UpdateStoreReq; +import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.domain.store.exception.UnathorizedMemberException; @@ -122,4 +123,38 @@ public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) return ResponseEntity.ok(apiResponse); } + + // 매장 세부사항 조회 + public ResponseEntity getStoreDetails(Long storeId) { + + Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + + // List storeBenefits = benefitRepository.findTypeByStoreId(storeId); + // Integer guestbookCount = guestBookRepository.countByStoreId(storeId); + // Integer likesCount = likesRepository.countByStoreId(storeId); + + GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() + .storeId(storeId) + .memberId(store.getMember().getId()) + .name(store.getName()) + .info(store.getInfo()) + .dongAreaId(store.getDongArea().getId()) + .detailAddress(store.getDetailAddress()) + .latitude(store.getLatitude()) + .longitude(store.getLongitude()) + .image(store.getImage()) + .stars(store.getStars()) + .type(store.getType()) + //.storeBenefits(storeBenefits.stream().map(BenefitType::getType).collect(Collectors.toList())) + //.guestbookCount(guestbookCount) + //.likesCount(likesCount) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(getStoreDetailRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java new file mode 100644 index 00000000..0569082b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -0,0 +1,58 @@ +package com.ttubeog.domain.store.dto.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ttubeog.domain.benefit.domain.BenefitType; +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GetStoreDetailRes { + + @Schema(description = "매장 ID") + private Long storeId; + + @Schema(description = "등록 유저 ID") + private Long memberId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Float latitude; + + @Schema(description = "경도") + private Float longitude; + + @Schema(description = "이미지") + private String image; + + @Schema(description = "별점") + private Float stars; + + @Schema(description = "업종") + private StoreType type; + + @Schema(description = "혜택 목록") + private List storeBenefits; + + @Schema(description = "방명록 수") + private Integer guestbookCount; + + @Schema(description = "좋아요 수") + private Integer likesCount; +} diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index f856a1fc..be6caaec 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; import com.ttubeog.domain.store.dto.request.UpdateStoreReq; +import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.config.security.token.CurrentUser; @@ -70,4 +71,17 @@ public ResponseEntity deleteStore( ) { return storeService.deleteStore(userPrincipal, storeId); } + + // 매장 세부사항 조회 + @Operation(summary = "매장 세부사항 조회", description = "매장 세부사항을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 세부사항 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetStoreDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "매장 세부사항 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/{storeId}") + public ResponseEntity getStoreDetails( + @PathVariable Long storeId + ) { + return storeService.getStoreDetails(storeId); + } } From b3ef021e83a94b706cf1d64b2978d85d3c7bd23e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 1 Feb 2024 23:43:51 +0900 Subject: [PATCH 194/356] =?UTF-8?q?[Feat]=20Store=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EB=88=84=EB=A5=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/presentation/StoreController.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index be6caaec..64596dbe 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.store.presentation; +import com.ttubeog.domain.likes.application.LikesService; import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; import com.ttubeog.domain.store.dto.request.UpdateStoreReq; @@ -29,6 +30,7 @@ public class StoreController { private final StoreService storeService; + private final LikesService likesService; // 매장 등록 @Operation(summary = "매장 등록", description = "매장을 등록합니다.") @@ -84,4 +86,18 @@ public ResponseEntity getStoreDetails( ) { return storeService.getStoreDetails(storeId); } + + // 매장 좋아요 누르기 + @Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "매장 좋아요 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "매장 좋아요 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping("/{storeId}/likes") + public ResponseEntity likesStore( + @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + @PathVariable Long storeId + ) { + return likesService.likesStore(userPrincipal, storeId); + } } From a135430c8b6fc5a34c923c5f921f7dd9cca0f51d Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 05:17:42 +0900 Subject: [PATCH 195/356] =?UTF-8?q?[Feat]=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20API=20=EC=9A=94=EC=B2=AD=EC=8B=9C=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20DB=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 17 ++++++++++++++++- .../member/presentation/MemberController.java | 12 ++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index b13039de..4ae3dbef 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.naming.spi.ResolveResult; import java.util.Optional; @RequiredArgsConstructor @@ -104,7 +105,6 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { refreshTokenService.saveTokenInfo(memberId, newRefreshToken, newAccessToken); - OAuthTokenResponse oAuthTokenResponse = new OAuthTokenResponse(newAccessToken, newRefreshToken, member.isRegisteredOAuthMember()); ApiResponse apiResponse = ApiResponse.builder() @@ -134,4 +134,19 @@ public ResponseEntity deleteLogout(HttpServletRequest request) { public void deleteValueByKey(String key) { redisTemplate.delete(key); } + + @Transactional + // 회원탈퇴 + public ResponseEntity deleteUser(HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberId(request); + Optional checkMember = memberRepository.findById(memberId); + memberRepository.delete(checkMember.get()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 5d20749b..5220ae95 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -73,4 +73,16 @@ public ResponseEntity logout( ) { return memberService.deleteLogout(request); } + + @Operation(summary = "회원탈퇴", description = "현재 접속된 회원이 탈퇴 합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "회원탈퇴 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "회원탈퇴 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @DeleteMapping("/delete") + public ResponseEntity deleteUser( + HttpServletRequest request + ) { + return memberService.deleteUser(request); + } } From 0f693b6d72d6ad1eb8b52931becb0cdc9cfa434e Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 05:43:37 +0900 Subject: [PATCH 196/356] =?UTF-8?q?[Feat]=2072=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=EB=8C=80=EA=B8=B0=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 19 ++++++++++++++++++- .../ttubeog/domain/member/domain/Member.java | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 4ae3dbef..3ca2ad35 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; @@ -22,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.naming.spi.ResolveResult; +import java.time.LocalDateTime; import java.util.Optional; @RequiredArgsConstructor @@ -32,6 +34,8 @@ public class MemberService { private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenService refreshTokenService; private final RedisTemplate redisTemplate; + private static final int WAITING_PERIOD_DAYS = 3; + // 현재 유저 조회 @@ -140,7 +144,20 @@ public void deleteValueByKey(String key) { public ResponseEntity deleteUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); Optional checkMember = memberRepository.findById(memberId); - memberRepository.delete(checkMember.get()); + + if (checkMember.isEmpty()) { + throw new InvalidMemberException(); + } + + Member member = checkMember.get(); + if (member.getStatus() == Status.INACTIVE) { + return ResponseEntity.badRequest().body(new InvalidMemberException("이미 탈퇴한 회원입니다.")); + } + + member = Member.builder().status(Status.INACTIVE).build(); + memberRepository.save(member); + + LocalDateTime deleteTime = LocalDateTime.now().plusDays(WAITING_PERIOD_DAYS); ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 2d8dd24f..c172a66b 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -54,6 +54,9 @@ public Member(String email, Platform platform, Status status, String memberNumbe this.memberNumber = memberNumber; } + public Member(Status status) { + this.status = status; + } public boolean isRegisteredOAuthMember() { return nickname != null; } From b09c1a65e1ccfdbbdf6879bdfbeece5d652fbd5c Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 9 Feb 2024 06:02:08 +0900 Subject: [PATCH 197/356] =?UTF-8?q?Chore:=20Benefit-Game=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Game을 생성할 때 Benefit이 종속되도록 수정했습니다. --- .../benefit/application/BenefitService.java | 223 +++++++++--------- .../domain/benefit/domain/Benefit.java | 22 +- .../domain/repository/BenefitRepository.java | 8 + .../repository/MemberBenefitRepository.java | 2 + .../benefit/dto/request/CreateBenefitReq.java | 3 + .../presentation/BenefitController.java | 106 ++++----- .../domain/game/application/GameService.java | 137 ++++++++--- .../com/ttubeog/domain/game/domain/Game.java | 9 +- .../domain/game/domain/RouletteGame.java | 2 +- .../domain/repository/GameRepository.java | 5 +- .../game/dto/request/CreateBasketballReq.java | 10 +- .../game/dto/request/CreateGiftReq.java | 10 +- .../game/dto/request/CreateRouletteReq.java | 7 +- .../game/dto/request/UpdateBasketballReq.java | 7 + .../game/dto/request/UpdateGiftReq.java | 7 + .../game/dto/request/UpdateRouletteReq.java | 6 +- .../dto/response/CreateBasketballRes.java | 13 +- .../game/dto/response/CreateGiftRes.java | 13 +- .../game/dto/response/CreateRouletteRes.java | 11 +- .../domain/game/dto/response/FindGameRes.java | 2 +- .../dto/response/RouletteBenefitResDto.java | 22 ++ .../dto/response/UpdateBasketballRes.java | 15 +- .../game/dto/response/UpdateGiftRes.java | 15 +- .../game/dto/response/UpdateRouletteRes.java | 8 +- .../game/presentation/GameController.java | 14 ++ 25 files changed, 446 insertions(+), 231 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 28a4741e..618a753c 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -18,6 +18,7 @@ import com.ttubeog.domain.game.domain.GameType; import com.ttubeog.domain.game.domain.repository.GameRepository; import com.ttubeog.domain.game.dto.response.FindGameRes; +import com.ttubeog.domain.game.exception.NonExistentGameException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -50,83 +51,83 @@ public class BenefitService { private final MemberBenefitRepository memberBenefitRepository; private final GameRepository gameRepository; - // 혜택 생성 - @Transactional - public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - -// Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); - - //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 - - Benefit benefit = Benefit.builder() - .content(createBenefitReq.getContent()) - .type(createBenefitReq.getType()) -// .store(store) - .build(); - - benefitRepository.save(benefit); - - CreateBenefitRes createBenefitRes = CreateBenefitRes.builder() - .benefitId(benefit.getId()) -// .storeId(benefit.getStore().getId()) - .content(benefit.getContent()) - .type(benefit.getType()) - .build(); - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(createBenefitRes) - .build(); - - return ResponseEntity.ok(apiResponse); - } - - // 혜택 삭제 - @Transactional - public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); - - //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 - - benefitRepository.delete(benefit); - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(Message.builder().message("혜택을 삭제했습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); - } - - //혜택 수정 - @Transactional - public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); - - //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 - - benefit.updateContent(updateBenefitReq.getContent()); - - UpdateBenefitRes updateBenefitRes = UpdateBenefitRes.builder() - .benefitId(benefit.getId()) - //.storeId(benefit.getStore().getId()) - .content(benefit.getContent()) - .type(benefit.getType()) - .build(); - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(updateBenefitRes) - .build(); - - return ResponseEntity.ok(apiResponse); - } +// // 혜택 생성 +// @Transactional +// public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { +// +// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); +// +//// Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); +// +// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 +// +// Benefit benefit = Benefit.builder() +// .content(createBenefitReq.getContent()) +// .type(createBenefitReq.getType()) +//// .store(store) +// .build(); +// +// benefitRepository.save(benefit); +// +// CreateBenefitRes createBenefitRes = CreateBenefitRes.builder() +// .benefitId(benefit.getId()) +//// .storeId(benefit.getStore().getId()) +// .content(benefit.getContent()) +// .type(benefit.getType()) +// .build(); +// +// ApiResponse apiResponse = ApiResponse.builder() +// .check(true) +// .information(createBenefitRes) +// .build(); +// +// return ResponseEntity.ok(apiResponse); +// } + +// // 혜택 삭제 +// @Transactional +// public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { +// +// Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); +// Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); +// +// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 +// +// benefitRepository.delete(benefit); +// +// ApiResponse apiResponse = ApiResponse.builder() +// .check(true) +// .information(Message.builder().message("혜택을 삭제했습니다.").build()) +// .build(); +// +// return ResponseEntity.ok(apiResponse); +// } + +// //혜택 수정 +// @Transactional +// public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { +// +// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); +// Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); +// +// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 +// +// benefit.updateContent(updateBenefitReq.getContent()); +// +// UpdateBenefitRes updateBenefitRes = UpdateBenefitRes.builder() +// .benefitId(benefit.getId()) +// //.storeId(benefit.getStore().getId()) +// .content(benefit.getContent()) +// .type(benefit.getType()) +// .build(); +// +// ApiResponse apiResponse = ApiResponse.builder() +// .check(true) +// .information(updateBenefitRes) +// .build(); +// +// return ResponseEntity.ok(apiResponse); +// } //게임 성공 후 혜택 저장 @Transactional @@ -234,40 +235,40 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page return ResponseEntity.ok(apiResponse); } - //혜택ID로 게임 조회 - public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); - List games = gameRepository.findAllByBenefit(benefit); - - List findGameResList = new ArrayList<>(); - for (Game game : games) { - FindGameRes.FindGameResBuilder builder = FindGameRes.builder() - .gameId(game.getId()) - .type(game.getType()); - - if (game.getType() == GameType.BASKETBALL) { - builder.timeLimit(game.getBasketballGame().getTimeLimit()) - .ballCount(game.getBasketballGame().getBallCount()) - .successCount(game.getBasketballGame().getSuccessCount()); - } else if (game.getType() == GameType.GIFT) { - builder.timeLimit(game.getGiftGame().getTimeLimit()) - .giftCount(game.getGiftGame().getGiftCount()); - } else if (game.getType() == GameType.ROULETTE) { - Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 - builder.options(game.getRouletteGame().getOptions()); - } - - findGameResList.add(builder.build()); - } - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(findGameResList) - .build(); - - return ResponseEntity.ok(apiResponse); - } +// //혜택ID로 게임 조회 +// public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { +// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); +// Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); +// Game game = gameRepository.findByBenefit(benefit).orElseThrow(NonExistentGameException::new); +// +// List findGameResList = new ArrayList<>(); +// for (Game game : games) { +// FindGameRes.FindGameResBuilder builder = FindGameRes.builder() +// .gameId(game.getId()) +// .type(game.getType()); +// +// if (game.getType() == GameType.BASKETBALL) { +// builder.timeLimit(game.getBasketballGame().getTimeLimit()) +// .ballCount(game.getBasketballGame().getBallCount()) +// .successCount(game.getBasketballGame().getSuccessCount()); +// } else if (game.getType() == GameType.GIFT) { +// builder.timeLimit(game.getGiftGame().getTimeLimit()) +// .giftCount(game.getGiftGame().getGiftCount()); +// } else if (game.getType() == GameType.ROULETTE) { +// Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 +// builder.options(game.getRouletteGame().getOptions()); +// } +// +// findGameResList.add(builder.build()); +// } +// +// ApiResponse apiResponse = ApiResponse.builder() +// .check(true) +// .information(findGameResList) +// .build(); +// +// return ResponseEntity.ok(apiResponse); +// } //한달지나면 expired true로 만들기 @Transactional diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index 90faf546..02aa8fc7 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -2,12 +2,9 @@ import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.game.domain.Game; -import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; import lombok.*; -import java.util.List; - @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -26,20 +23,25 @@ public class Benefit extends BaseEntity { private BenefitType type; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "store_id") - private Store store; + @JoinColumn(name = "game_id") + private Game game; - @OneToMany(mappedBy = "benefit", cascade = CascadeType.ALL, orphanRemoval = true) - private List game; +// @OneToMany(mappedBy = "benefit", cascade = CascadeType.ALL, orphanRemoval = true) +// private List game; @Builder - public Benefit(String content, BenefitType type, Store store) { + public Benefit(String content, BenefitType type, Game game) { this.content = content; this.type = type; - this.store = store; + this.game = game; } - public void updateContent(String content) { + public void updateBenefit(String content, BenefitType type) { this.content = content; + this.type = type; + } + + public void deleteGame() { + this.game = null; } } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java index 49c15d17..25235760 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java @@ -1,9 +1,17 @@ package com.ttubeog.domain.benefit.domain.repository; import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.game.domain.Game; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + @Repository public interface BenefitRepository extends JpaRepository { + + Optional findByGame(Game game); + + List findAllByGame(Game game); } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index c76aee9d..c9987675 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -22,4 +22,6 @@ public interface MemberBenefitRepository extends JpaRepository findAllByExpiredFalse(); Page findAllByMember(Member member, PageRequest pageRequest); + + List findAllByMemberAndBenefitIn(Member member, List benefits); } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java index c42256cf..85c307b0 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java @@ -13,6 +13,9 @@ public class CreateBenefitReq { // @Schema(description = "매장 ID", example = "1") // private Long storeId; + @Schema(description = "게임 ID", example = "1") + private Long gameId; + @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 2495dcc3..77e1949b 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -31,47 +31,47 @@ public class BenefitController { private final BenefitService benefitService; - //혜택 생성 - @Operation(summary = "혜택 생성", description = "매장의 혜택을 생성합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "혜택 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "혜택 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), - }) - @PostMapping - public ResponseEntity createBenefit( - @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody CreateBenefitReq createBenefitReq - ) throws JsonProcessingException { - return benefitService.createBenefit(userPrincipal, createBenefitReq); - } +// //혜택 생성 +// @Operation(summary = "혜택 생성", description = "매장의 혜택을 생성합니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "혜택 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), +// @ApiResponse(responseCode = "400", description = "혜택 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), +// }) +// @PostMapping +// public ResponseEntity createBenefit( +// @CurrentUser UserPrincipal userPrincipal, +// @Valid @RequestBody CreateBenefitReq createBenefitReq +// ) throws JsonProcessingException { +// return benefitService.createBenefit(userPrincipal, createBenefitReq); +// } - //혜택 삭제 - @Operation(summary = "혜택 삭제", description = "매장의 혜택을 삭제합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "혜택 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), - @ApiResponse(responseCode = "400", description = "혜택 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), - }) - @DeleteMapping("/{benefitId}") - public ResponseEntity deleteBenefit( - @CurrentUser UserPrincipal userPrincipal, - @PathVariable(value = "benefitId") Long benefitId - ) throws JsonProcessingException { - return benefitService.deleteBenefit(userPrincipal, benefitId); - } +// //혜택 삭제 +// @Operation(summary = "혜택 삭제", description = "매장의 혜택을 삭제합니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "혜택 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), +// @ApiResponse(responseCode = "400", description = "혜택 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), +// }) +// @DeleteMapping("/{benefitId}") +// public ResponseEntity deleteBenefit( +// @CurrentUser UserPrincipal userPrincipal, +// @PathVariable(value = "benefitId") Long benefitId +// ) throws JsonProcessingException { +// return benefitService.deleteBenefit(userPrincipal, benefitId); +// } //혜택 수정 - @Operation(summary = "혜택 수정", description = "매장의 혜택을 수정합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "혜택 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBenefitRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "혜택 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), - }) - @PatchMapping - public ResponseEntity updateBenefit( - @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody UpdateBenefitReq updateBenefitReq - ) throws JsonProcessingException { - return benefitService.updateBenefit(userPrincipal, updateBenefitReq); - } +// @Operation(summary = "혜택 수정", description = "매장의 혜택을 수정합니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "혜택 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBenefitRes.class) ) } ), +// @ApiResponse(responseCode = "400", description = "혜택 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), +// }) +// @PatchMapping +// public ResponseEntity updateBenefit( +// @CurrentUser UserPrincipal userPrincipal, +// @Valid @RequestBody UpdateBenefitReq updateBenefitReq +// ) throws JsonProcessingException { +// return benefitService.updateBenefit(userPrincipal, updateBenefitReq); +// } //게임 성공 후 혜택 저장 @Operation(summary = "혜택 저장", description = "게임 성공 후 혜택을 저장합니다.") @@ -88,7 +88,7 @@ public ResponseEntity saveBenefit( } //혜택 사용 - @Operation(summary = "혜택 사용", description = "멤버가 보유 중인 혜택을 사용합니다.") + @Operation(summary = "내 혜택 사용", description = "멤버가 보유 중인 혜택을 사용합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "혜택 사용 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), @ApiResponse(responseCode = "400", description = "혜택 사용 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), @@ -102,7 +102,7 @@ public ResponseEntity useBenefit( } //혜택 조회 - @Operation(summary = "혜택 조회", description = "멤버가 보유 중인 혜택을 모두 조회합니다. 페이지 번호 0번이 첫 번째 페이지 입니다.") + @Operation(summary = "내 혜택 조회", description = "멤버가 보유 중인 혜택을 모두 조회합니다. 페이지 번호 0번이 첫 번째 페이지 입니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "혜택 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), @ApiResponse(responseCode = "400", description = "혜택 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), @@ -115,17 +115,17 @@ public ResponseEntity findMyBenefit( return benefitService.findMyBenefit(userPrincipal, page); } - //혜택으로 모든 게임 조회 - @Operation(summary = "혜택으로 게임 조회", description = "혜택에 해당하는 게임을 모두 조회합니다. 최대 3개입니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "게임 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), - @ApiResponse(responseCode = "400", description = "게임 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), - }) - @GetMapping("/{benefitId}/game") - public ResponseEntity findGames( - @CurrentUser UserPrincipal userPrincipal, - @PathVariable(value = "benefitId") Long benefitId - ) throws JsonProcessingException { - return benefitService.findGames(userPrincipal, benefitId); - } +// //혜택으로 모든 게임 조회 +// @Operation(summary = "혜택으로 게임 조회", description = "혜택에 해당하는 게임을 모두 조회합니다. 최대 3개입니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "게임 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), +// @ApiResponse(responseCode = "400", description = "게임 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), +// }) +// @GetMapping("/{benefitId}/game") +// public ResponseEntity findGames( +// @CurrentUser UserPrincipal userPrincipal, +// @PathVariable(value = "benefitId") Long benefitId +// ) throws JsonProcessingException { +// return benefitService.findGames(userPrincipal, benefitId); +// } } diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 961d148e..07459327 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -2,14 +2,16 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.game.domain.*; import com.ttubeog.domain.game.domain.repository.*; import com.ttubeog.domain.game.dto.request.*; import com.ttubeog.domain.game.dto.response.*; import com.ttubeog.domain.game.exception.NonExistentGameException; -import com.ttubeog.domain.game.exception.OverlappingGameException; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.config.security.token.UserPrincipal; @@ -21,6 +23,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.stream.Collectors; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -32,27 +37,28 @@ public class GameService { private final GiftGameRepository giftGameRepository; private final BasketBallRepository basketBallRepository; private final RouletteRepository rouletteRepository; + private final MemberBenefitRepository memberBenefitRepository; // 선물게임 생성 @Transactional public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq createGiftReq) throws JsonProcessingException { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(createGiftReq.getBenefitId() - ).orElseThrow(NonExistentBenefitException::new); - - //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.GIFT)) { - throw new OverlappingGameException(); - } Game game = Game.builder() - .benefit(benefit) .type(GameType.GIFT) .build(); gameRepository.save(game); + Benefit benefit = Benefit.builder() + .content(createGiftReq.getBenefitContent()) + .type(createGiftReq.getBenefitType()) + .game(game) + .build(); + + benefitRepository.save(benefit); + GiftGame giftGame = GiftGame.builder() .game(game) .timeLimit(createGiftReq.getTimeLimit()) @@ -66,6 +72,8 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c .benefitId(benefit.getId()) .giftCount(giftGame.getGiftCount()) .timeLimit(giftGame.getTimeLimit()) + .benefitType(benefit.getType()) + .benefitContent(benefit.getContent()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -81,21 +89,21 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBasketballReq createBasketballReq) throws JsonProcessingException { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(createBasketballReq.getBenefitId() - ).orElseThrow(NonExistentBenefitException::new); - - //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.BASKETBALL)) { - throw new OverlappingGameException(); - } Game game = Game.builder() - .benefit(benefit) .type(GameType.BASKETBALL) .build(); gameRepository.save(game); + Benefit benefit = Benefit.builder() + .content(createBasketballReq.getBenefitContent()) + .type(createBasketballReq.getBenefitType()) + .game(game) + .build(); + + benefitRepository.save(benefit); + BasketballGame basketballGame = BasketballGame.builder() .game(game) .timeLimit(createBasketballReq.getTimeLimit()) @@ -111,6 +119,8 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas .timeLimit(basketballGame.getTimeLimit()) .ballCount(basketballGame.getBallCount()) .successCount(basketballGame.getSuccessCount()) + .benefitType(benefit.getType()) + .benefitContent(benefit.getContent()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -126,29 +136,39 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRouletteReq createRouletteReq) throws JsonProcessingException { memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Benefit benefit = benefitRepository.findById(createRouletteReq.getBenefitId() - ).orElseThrow(NonExistentBenefitException::new); - - //하나의 혜택에 같은 종류 Game이 들어갈 수 없음 - if (gameRepository.existsByBenefitAndType(benefit, GameType.ROULETTE)) { - throw new OverlappingGameException(); - } Game game = Game.builder() - .benefit(benefit) .type(GameType.ROULETTE) .build(); gameRepository.save(game); + List benefitList = createRouletteReq.getOptions().stream() + .map(option -> Benefit.builder() + .content(option) + .type(createRouletteReq.getBenefitType()) + .game(game) + .build()) + .collect(Collectors.toList()); + + benefitRepository.saveAll(benefitList); + RouletteGame rouletteGame = RouletteGame.builder() .game(game) .options(createRouletteReq.getOptions()) .build(); rouletteRepository.save(rouletteGame); + List benefitResDtoList = benefitList.stream() + .map(benefit -> RouletteBenefitResDto.builder() + .benefitId(benefit.getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build()) + .collect(Collectors.toList()); + CreateRouletteRes createRouletteRes = CreateRouletteRes.builder() .gameId(rouletteGame.getId()) - .benefitId(benefit.getId()) + .benefits(benefitResDtoList) .options(rouletteGame.getOptions()) .build(); @@ -166,14 +186,19 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); + Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); giftGame.updateGiftCount(updateGiftReq.getGiftCount()); + benefit.updateBenefit(updateGiftReq.getBenefitContent(), updateGiftReq.getBenefitType()); UpdateGiftRes updateGiftRes = UpdateGiftRes.builder() .gameId(giftGame.getId()) .giftCount(giftGame.getGiftCount()) .timeLimit(giftGame.getTimeLimit()) + .benefitId(benefit.getId()) + .benefitContent(benefit.getContent()) + .benefitType(benefit.getType()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -190,16 +215,21 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); + Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); basketballGame.updateTimeLimit(updateBasketballReq.getTimeLimit()); + benefit.updateBenefit(updateBasketballReq.getBenefitContent(), updateBasketballReq.getBenefitType()); UpdateBasketballRes updateBasketballRes = UpdateBasketballRes.builder() .gameId(basketballGame.getId()) .ballCount(basketballGame.getBallCount()) .timeLimit(basketballGame.getTimeLimit()) .successCount(basketballGame.getSuccessCount()) + .benefitId(benefit.getId()) + .benefitContent(benefit.getContent()) + .benefitType(benefit.getType()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -216,12 +246,33 @@ public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRoule memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); + List benefitList = benefitRepository.findAllByGame(rouletteGame.getGame()); + benefitList.forEach(benefit -> benefit.deleteGame()); + + List newBenefitList = updateRouletteReq.getOptions().stream() + .map(option -> Benefit.builder() + .content(option) + .type(updateRouletteReq.getBenefitType()) + .game(rouletteGame.getGame()) + .build()) + .collect(Collectors.toList()); + + benefitRepository.saveAll(newBenefitList); + + rouletteGame.updateRoulette(updateRouletteReq.getOptions()); - rouletteGame.updateOptions(updateRouletteReq.getOptions()); + List benefitResDtoList = newBenefitList.stream() + .map(benefit -> RouletteBenefitResDto.builder() + .benefitId(benefit.getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build()) + .collect(Collectors.toList()); UpdateRouletteRes updateRouletteRes = UpdateRouletteRes.builder() .gameId(rouletteGame.getId()) .options(rouletteGame.getOptions()) + .benefits(benefitResDtoList) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -236,9 +287,13 @@ public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRoule @Transactional public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); - Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); + Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); + List benefitList = benefitRepository.findAllByGame(game); + List memberBenefitList = memberBenefitRepository.findAllByMemberAndBenefitIn(member, benefitList); + memberBenefitRepository.deleteAll(memberBenefitList); + benefitRepository.deleteAll(benefitList); gameRepository.delete(game); ApiResponse apiResponse = ApiResponse.builder() @@ -282,4 +337,28 @@ public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) thro return ResponseEntity.ok(apiResponse); } + //게임ID로 혜택 조회 + @Transactional + public ResponseEntity findBenefit(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { + + memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); + List benefitList = benefitRepository.findAllByGame(game); + + List benefitResDtoList = benefitList.stream() + .map(benefit -> RouletteBenefitResDto.builder() + .benefitId(benefit.getId()) + .content(benefit.getContent()) + .type(benefit.getType()) + .build()) + .collect(Collectors.toList()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(benefitResDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + } diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index 724bdb9a..e84376df 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -23,8 +24,8 @@ public class Game extends BaseEntity { private GameType type; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "benefit_id") - private Benefit benefit; + @JoinColumn(name = "store_id") + private Store store; @OneToOne(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) private GiftGame giftGame; @@ -36,8 +37,8 @@ public class Game extends BaseEntity { private RouletteGame rouletteGame; @Builder - public Game(GameType type, Benefit benefit) { + public Game(GameType type, Store store) { this.type = type; - this.benefit = benefit; + this.store = store; } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java index c19d3a3e..6aee27b4 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/RouletteGame.java @@ -34,7 +34,7 @@ public RouletteGame(Game game, List options) { this.options = options; } - public void updateOptions(List options) { + public void updateRoulette(List options) { this.options = options; } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java index cc73f51e..2ddf189d 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java @@ -7,11 +7,12 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface GameRepository extends JpaRepository { - Boolean existsByBenefitAndType(Benefit benefit, GameType type); +// Boolean existsByBenefitAndType(Benefit benefit, GameType type); - List findAllByBenefit(Benefit benefit); +// Optional findByBenefit(Benefit benefit); } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java index cb127e23..9c553846 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -9,8 +10,7 @@ @Schema(description = "CreateBasketballGameRequest") public class CreateBasketballReq { - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; +// private Long StoreId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -20,4 +20,10 @@ public class CreateBasketballReq { @Schema(description = "성공 개수", example = "4") private Integer successCount; + + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java index 3aa2dd1d..fe7a1ce1 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -9,12 +10,17 @@ @Schema(description = "CreateGiftGameRequest") public class CreateGiftReq { - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; + // private Long StoreId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; + + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java index a5fc84ad..4f3d1d68 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -9,9 +10,9 @@ @Schema(description = "CreateRouletteGameRequest") public class CreateRouletteReq { - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; + @Schema(description = "혜택 타입", example = "SALE") + private BenefitType benefitType; - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java index c5b0c2b7..963bf7c6 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -20,4 +21,10 @@ public class UpdateBasketballReq { @Schema(description = "성공 개수", example = "4") private Integer successCount; + + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java index efa9261d..ced4904a 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -17,4 +18,10 @@ public class UpdateGiftReq { @Schema(description = "선물개수", example = "3") private Integer giftCount; + + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java index 75be6d99..570f3857 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.request; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -11,7 +12,10 @@ public class UpdateRouletteReq { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + @Schema(description = "혜택 타입", example = "SALE") + private BenefitType benefitType; + + @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java index 0e9135bf..b02fd694 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.response; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -15,6 +16,8 @@ public class CreateBasketballRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; + // private Long StoreId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -24,12 +27,20 @@ public class CreateBasketballRes { @Schema(description = "성공 개수", example = "4") private Integer successCount; + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; + @Builder - public CreateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount) { + public CreateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; + this.benefitContent = benefitContent; + this.benefitType = benefitType; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java index 5d266949..5de8eb64 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.response; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -15,17 +16,27 @@ public class CreateGiftRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; + // private Long StoreId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; + @Builder - public CreateGiftRes(Long benefitId, Long gameId, LocalTime timeLimit, Integer giftCount) { + public CreateGiftRes(Long benefitId, Long gameId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.benefitId = benefitId; this.gameId = gameId; this.timeLimit = timeLimit; this.giftCount = giftCount; + this.benefitContent = benefitContent; + this.benefitType = benefitType; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java index 7e22febb..e4ba9ac8 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -12,16 +12,15 @@ public class CreateRouletteRes { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; - - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; + private List benefits; + @Builder - public CreateRouletteRes(Long gameId, Long benefitId, List options) { + public CreateRouletteRes(Long gameId, List options, List benefits) { this.gameId = gameId; - this.benefitId = benefitId; this.options = options; + this.benefits = benefits; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 883fb67c..9e5cb8f1 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -33,7 +33,7 @@ public class FindGameRes { private List options; @Builder - public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { + public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { this.gameId = gameId; this.type = type; this.timeLimit = timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java b/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java new file mode 100644 index 00000000..75672734 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java @@ -0,0 +1,22 @@ +package com.ttubeog.domain.game.dto.response; + +import com.ttubeog.domain.benefit.domain.BenefitType; +import lombok.Builder; +import lombok.Data; + +@Data +public class RouletteBenefitResDto { + + private Long benefitId; + + private String content; + + private BenefitType type; + + @Builder + public RouletteBenefitResDto(Long benefitId, String content, BenefitType type) { + this.benefitId = benefitId; + this.content = content; + this.type = type; + } +} diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java index 0675bf34..2038fbc9 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.response; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -12,6 +13,9 @@ public class UpdateBasketballRes { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -21,11 +25,20 @@ public class UpdateBasketballRes { @Schema(description = "성공 개수", example = "4") private Integer successCount; + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; + @Builder - public UpdateBasketballRes(Long gameId, LocalTime timeLimit, Integer ballCount, Integer successCount) { + public UpdateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; + this.benefitId = benefitId; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; + this.benefitContent = benefitContent; + this.benefitType = benefitType; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java index 04a26ece..593a3df1 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.response; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -12,16 +13,28 @@ public class UpdateGiftRes { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "혜택 ID", example = "1") + private Long benefitId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") + private String benefitContent; + + @Schema(description = "혜택 종류", example = "SALE") + private BenefitType benefitType; + @Builder - public UpdateGiftRes(Long gameId, LocalTime timeLimit, Integer giftCount) { + public UpdateGiftRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; + this.benefitId = benefitId; this.timeLimit = timeLimit; this.giftCount = giftCount; + this.benefitContent = benefitContent; + this.benefitType = benefitType; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java index 07547053..ef6e598a 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.game.dto.response; +import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -12,12 +13,15 @@ public class UpdateRouletteRes { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") + @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; + private List benefits; + @Builder - public UpdateRouletteRes(Long gameId, List options) { + public UpdateRouletteRes(Long gameId, List options, List benefits) { this.gameId = gameId; this.options = options; + this.benefits = benefits; } } diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index 29cb6f75..a3e393d4 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -139,4 +139,18 @@ public ResponseEntity findGame( return gameService.findGame(userPrincipal, gameId); } + //게임 조회 + @Operation(summary = "혜택 조회", description = "게임Id로 혜택 정보를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = RouletteBenefitResDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @GetMapping("/{gameId}/benefit") + public ResponseEntity findBenefit( + @CurrentUser UserPrincipal userPrincipal, + @PathVariable(value = "gameId") Long gameId + ) throws JsonProcessingException { + return gameService.findBenefit(userPrincipal, gameId); + } + } From ded9f4801773bc519ca35bc03e4c25abc6d6abf0 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 9 Feb 2024 06:07:55 +0900 Subject: [PATCH 198/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EA=B0=92=20=EC=84=A4=EC=A0=95=20isUsed?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=EB=B6=84=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 56 ++++++++++++++++++- .../domain/repository/MemberRepository.java | 3 + .../member/dto/response/MemberDetailRes.java | 2 + 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index b13039de..bd042700 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.member.application; +import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.auth.exception.AccessTokenExpiredException; import com.ttubeog.domain.auth.exception.InvalidAccessTokenException; @@ -21,6 +22,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.naming.spi.ResolveResult; +import java.time.LocalDateTime; import java.util.Optional; @RequiredArgsConstructor @@ -31,6 +34,8 @@ public class MemberService { private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenService refreshTokenService; private final RedisTemplate redisTemplate; + private static final int WAITING_PERIOD_DAYS = 3; + // 현재 유저 조회 @@ -55,10 +60,29 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { return ResponseEntity.ok(apiResponse); } - // 닉네임 설정 @Transactional public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); + + if (memberRepository.existsByNickname(produceNicknameRequest.getNickname())) { + Optional checkMember = memberRepository.findById(memberId); + Member member = checkMember.get(); + + MemberDetailRes memberDetailRes = MemberDetailRes.builder() + .id(member.getId()) + .name(member.getNickname()) + .platform(member.getPlatform()) + .isUsed(false) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(memberDetailRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } + memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); Optional checkMember = memberRepository.findById(memberId); @@ -69,6 +93,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN .id(member.getId()) .name(member.getNickname()) .platform(member.getPlatform()) + .isUsed(true) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -104,7 +129,6 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { refreshTokenService.saveTokenInfo(memberId, newRefreshToken, newAccessToken); - OAuthTokenResponse oAuthTokenResponse = new OAuthTokenResponse(newAccessToken, newRefreshToken, member.isRegisteredOAuthMember()); ApiResponse apiResponse = ApiResponse.builder() @@ -134,4 +158,32 @@ public ResponseEntity deleteLogout(HttpServletRequest request) { public void deleteValueByKey(String key) { redisTemplate.delete(key); } + + @Transactional + // 회원탈퇴 + public ResponseEntity deleteUser(HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberId(request); + Optional checkMember = memberRepository.findById(memberId); + + if (checkMember.isEmpty()) { + throw new InvalidMemberException(); + } + + Member member = checkMember.get(); + if (member.getStatus() == Status.INACTIVE) { + return ResponseEntity.badRequest().body(new InvalidMemberException("이미 탈퇴한 회원입니다.")); + } + + member = Member.builder().status(Status.INACTIVE).build(); + memberRepository.save(member); + + LocalDateTime deleteTime = LocalDateTime.now().plusDays(WAITING_PERIOD_DAYS); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index f9889abb..ebb7d157 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -36,4 +36,7 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") void updateUserNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); + + Boolean existsByNickname(String nickname); + } diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index b9db943b..726d3f82 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -19,6 +19,8 @@ public class MemberDetailRes { private Platform platform; + private Boolean isUsed; + public static MemberDetailRes toDto(Member member) { return MemberDetailRes.builder() .id(member.getId()) From d53560bd42d3b21edaeba618a03e12b38a752455 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 06:12:09 +0900 Subject: [PATCH 199/356] =?UTF-8?q?[Chore]=20Store=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=ED=99=95=EC=9D=B8=20=EB=B0=A9=EB=B2=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/application/StoreService.java | 31 +++++++++++++------ .../store/presentation/StoreController.java | 24 +++++++------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 30518659..6fe21f3d 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -1,6 +1,8 @@ package com.ttubeog.domain.store.application; import com.ttubeog.domain.area.domain.DongArea; +import com.ttubeog.domain.area.domain.repository.DongAreaRepository; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.store.domain.Store; @@ -10,12 +12,14 @@ import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; +import com.ttubeog.domain.store.exception.InvalidDongAreaException; import com.ttubeog.domain.store.exception.UnathorizedMemberException; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -28,17 +32,22 @@ public class StoreService { private final StoreRepository storeRepository; private final MemberRepository memberRepository; + private final DongAreaRepository dongAreaRepository; + private final JwtTokenProvider jwtTokenProvider; // 매장 등록 @Transactional - public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStoreReq registerStoreReq) { + public ResponseEntity registerStore(HttpServletRequest request, RegisterStoreReq registerStoreReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + DongArea dongArea = dongAreaRepository.findById(registerStoreReq.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); Store store = Store.builder() .name(registerStoreReq.getName()) .info(registerStoreReq.getInfo()) - .dongArea(new DongArea(registerStoreReq.getDongAreaId())) + .dongArea(dongArea) .detailAddress(registerStoreReq.getDetailAddress()) .latitude(registerStoreReq.getLatitude()) .longitude(registerStoreReq.getLongitude()) @@ -71,13 +80,14 @@ public ResponseEntity registerStore(UserPrincipal userPrincipal, RegisterStor // 매장 수정 @Transactional - public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq updateStoreReq) { + public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq updateStoreReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(updateStoreReq.getStoreId()).orElseThrow(NonExistentStoreException::new); Member storeOwner = store.getMember(); - if (storeOwner.getId() != member.getId()) { + if (!storeOwner.getId().equals(memberId)) { throw new UnathorizedMemberException(); } @@ -110,9 +120,10 @@ public ResponseEntity updateStore(UserPrincipal userPrincipal, UpdateStoreReq // 매장 삭제 @Transactional - public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) { + public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); storeRepository.delete(store); @@ -125,8 +136,10 @@ public ResponseEntity deleteStore(UserPrincipal userPrincipal, Long storeId) } // 매장 세부사항 조회 - public ResponseEntity getStoreDetails(Long storeId) { + public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeId) { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); // List storeBenefits = benefitRepository.findTypeByStoreId(storeId); diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 64596dbe..90acb75b 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -40,10 +41,10 @@ public class StoreController { }) @PostMapping public ResponseEntity registerStore( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody RegisterStoreReq registerStoreReq ) { - return storeService.registerStore(userPrincipal, registerStoreReq); + return storeService.registerStore(request, registerStoreReq); } // 매장 수정 @@ -54,10 +55,10 @@ public ResponseEntity registerStore( }) @PatchMapping public ResponseEntity updateStore( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateStoreReq updateStoreReq ) { - return storeService.updateStore(userPrincipal, updateStoreReq); + return storeService.updateStore(request, updateStoreReq); } // 매장 삭제 @@ -68,10 +69,10 @@ public ResponseEntity updateStore( }) @DeleteMapping("/{storeId}") public ResponseEntity deleteStore( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable Long storeId ) { - return storeService.deleteStore(userPrincipal, storeId); + return storeService.deleteStore(request, storeId); } // 매장 세부사항 조회 @@ -82,22 +83,23 @@ public ResponseEntity deleteStore( }) @GetMapping("/{storeId}") public ResponseEntity getStoreDetails( + HttpServletRequest request, @PathVariable Long storeId ) { - return storeService.getStoreDetails(storeId); + return storeService.getStoreDetails(request, storeId); } // 매장 좋아요 누르기 - @Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") + /*Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "매장 좋아요 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @ApiResponse(responseCode = "400", description = "매장 좋아요 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping("/{storeId}/likes") public ResponseEntity likesStore( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable Long storeId ) { - return likesService.likesStore(userPrincipal, storeId); - } + return likesService.likesStore(request, storeId); + }*/ } From e5f998fdf5259c80facd9169f4b9a74876fef9a7 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 06:13:46 +0900 Subject: [PATCH 200/356] =?UTF-8?q?[Feat]=20DongArea=20=EA=B4=80=ED=98=84?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/area/domain/DongArea.java | 7 +------ .../domain/store/exception/InvalidDongAreaException.java | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/exception/InvalidDongAreaException.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java index 77f27a11..c797af52 100644 --- a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java +++ b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java @@ -2,21 +2,16 @@ import com.ttubeog.domain.common.BaseEntity; import jakarta.persistence.*; -import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @Entity @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "dong_area") +@NoArgsConstructor public class DongArea extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - public DongArea(Long id) { - this.id = id; - } } diff --git a/src/main/java/com/ttubeog/domain/store/exception/InvalidDongAreaException.java b/src/main/java/com/ttubeog/domain/store/exception/InvalidDongAreaException.java new file mode 100644 index 00000000..fdad5488 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/InvalidDongAreaException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class InvalidDongAreaException extends RuntimeException { + + public InvalidDongAreaException() { + super("유효하지 않은 지역 정보입니다."); + } +} From 0ac603d09b9ea9f4bf5df8cd44f47a58e80aaf7d Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 06:16:25 +0900 Subject: [PATCH 201/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 1 - src/main/java/com/ttubeog/domain/store/domain/Store.java | 2 -- .../com/ttubeog/domain/store/presentation/StoreController.java | 3 --- 3 files changed, 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 6fe21f3d..765b4512 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -15,7 +15,6 @@ import com.ttubeog.domain.store.exception.InvalidDongAreaException; import com.ttubeog.domain.store.exception.UnathorizedMemberException; import com.ttubeog.domain.store.exception.NonExistentStoreException; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index e1c9b5a1..4229683a 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -6,8 +6,6 @@ import jakarta.persistence.*; import lombok.*; -import java.util.List; - @Entity @Getter @Builder diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 90acb75b..4801bc2c 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -7,11 +7,8 @@ import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; From d8e4d0124d8ccb88cb248f3f0203fedfaa95c835 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 9 Feb 2024 06:51:42 +0900 Subject: [PATCH 202/356] [Feat] implement image domain --- .../domain/guestbook/domain/GuestBook.java | 2 + .../InvalidGuestBookIdException.java | 8 ++ .../image/application/ImageService.java | 88 +++++++++++++++++-- .../ttubeog/domain/image/domain/Image.java | 19 +++- .../domain/image/domain/ImageType.java | 10 +++ .../dto/request/CreateImageRequestDto.java | 3 +- .../image/dto/request/ImageRequestType.java | 6 -- .../dto/request/UpdateImageRequestDto.java | 4 +- .../image/dto/response/ImageResponseDto.java | 5 +- .../exception/InvalidImageTypeException.java | 8 ++ .../domain/spot/application/SpotService.java | 27 +++--- 11 files changed, 151 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookIdException.java create mode 100644 src/main/java/com/ttubeog/domain/image/domain/ImageType.java delete mode 100644 src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java create mode 100644 src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java index 3864e46d..b42c4d0c 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java @@ -5,7 +5,9 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.Getter; +@Getter @Entity public class GuestBook extends BaseEntity { diff --git a/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookIdException.java b/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookIdException.java new file mode 100644 index 00000000..3ba2bae2 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookIdException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.guestbook.exception; + +public class InvalidGuestBookIdException extends RuntimeException { + + public InvalidGuestBookIdException() { + super("올바르지 않은 방명록 ID 입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index a535c44c..47479dd9 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -1,24 +1,25 @@ package com.ttubeog.domain.image.application; +import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; +import com.ttubeog.domain.guestbook.exception.InvalidGuestBookIdException; import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; import com.ttubeog.domain.image.dto.response.ImageResponseDto; import com.ttubeog.domain.image.exception.InvalidImageException; +import com.ttubeog.domain.image.exception.InvalidImageTypeException; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.repository.StoreRepository; import lombok.RequiredArgsConstructor; -import org.springframework.security.core.parameters.P; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import static com.ttubeog.domain.image.dto.request.ImageRequestType.SPOT; - @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -27,6 +28,7 @@ public class ImageService { private final ImageRepository imageRepository; private final SpotRepository spotRepository; private final StoreRepository storeRepository; + private final GuestBookRepository guestBookRepository; public static List getImageString(List imageList) { List imageString = new ArrayList<>(); @@ -38,32 +40,82 @@ public static List getImageString(List imageList) { return imageString; } + public ImageResponseDto findById(Long imageId) { + Image image = imageRepository.findById(imageId).orElseThrow(InvalidImageException::new); + ImageResponseDto imageResponseDto = new ImageResponseDto(); + if (image.getImageType().equals(ImageType.SPOT)) { + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .image(image.getImage()) + .imageType(image.getImageType()) + .placeId(image.getSpot().getId()) + .build(); + } else if (image.getImageType().equals(ImageType.STORE)) { + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .image(image.getImage()) + .imageType(image.getImageType()) + .placeId(image.getStore().getId()) + .build(); + } else if (image.getImageType().equals(ImageType.GUESTBOOK)) { + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .image(image.getImage()) + .imageType(image.getImageType()) + .placeId(image.getGuestBook().getId()) + .build(); + } else { + throw new InvalidImageTypeException(); + } + + return imageResponseDto; + } + @Transactional public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) { Image image; ImageResponseDto imageResponseDto; - if (createImageRequestDto.imageRequestType == SPOT) { + if (createImageRequestDto.getImageType().equals(ImageType.SPOT)) { image = Image.builder() .image(createImageRequestDto.getImage()) + .imageType(createImageRequestDto.getImageType()) .spot(spotRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() .id(image.getId()) + .imageType(image.getImageType()) .placeId(image.getSpot().getId()) .build(); - } else { + } else if (createImageRequestDto.getImageType().equals(ImageType.STORE)){ image = Image.builder() .image(createImageRequestDto.getImage()) + .imageType(createImageRequestDto.getImageType()) .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() .id(image.getId()) + .imageType(image.getImageType()) .placeId(image.getStore().getId()) .build(); + } else if (createImageRequestDto.getImageType().equals(ImageType.GUESTBOOK)) { + image = Image.builder() + .image(createImageRequestDto.getImage()) + .imageType(createImageRequestDto.getImageType()) + .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .build(); + + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .imageType(image.getImageType()) + .placeId(image.getStore().getId()) + .build(); + } else { + throw new InvalidImageTypeException(); } + imageRepository.save(image); return imageResponseDto; @@ -73,20 +125,42 @@ public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) { Image image = imageRepository.findById(updateImageRequestDto.getId()).orElseThrow(InvalidImageException::new); + + if (!image.getImageType().equals(updateImageRequestDto.getImageType())) { + throw new InvalidImageTypeException(); + } + ImageResponseDto imageResponseDto; - if (updateImageRequestDto.imageRequestType == SPOT) { + + + if (updateImageRequestDto.getImageType().equals(ImageType.SPOT)) { image.updateImage(updateImageRequestDto.getImage(), spotRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + imageResponseDto = ImageResponseDto.builder() .id(image.getId()) + .imageType(image.getImageType()) .placeId(image.getSpot().getId()) .build(); - } else { + } else if (updateImageRequestDto.getImageType().equals(ImageType.STORE)){ + // TODO 스토어 exception 수정하기 image.updateImage(updateImageRequestDto.getImage(), storeRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + imageResponseDto = ImageResponseDto.builder() .id(image.getId()) + .imageType(image.getImageType()) .placeId(image.getStore().getId()) .build(); + } else if (updateImageRequestDto.getImageType().equals(ImageType.GUESTBOOK)) { + image.updateImage(updateImageRequestDto.getImage(), guestBookRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidGuestBookIdException::new)); + + imageResponseDto = ImageResponseDto.builder() + .id(image.getId()) + .imageType(image.getImageType()) + .placeId(image.getStore().getId()) + .build(); + } else { + throw new InvalidImageTypeException(); } imageRepository.save(image); diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java index 4bf92064..bcf46099 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/Image.java +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.image.domain; import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; @@ -10,6 +11,8 @@ import lombok.NoArgsConstructor; import org.apache.ibatis.annotations.Many; +import javax.imageio.ImageTypeSpecifier; + @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @@ -24,6 +27,9 @@ public class Image extends BaseEntity { @Column(name = "image", nullable = false) private String image; + @Column(name = "image_type", nullable = false) + private ImageType imageType; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "spot") private Spot spot; @@ -32,11 +38,17 @@ public class Image extends BaseEntity { @JoinColumn(name = "store") private Store store; - public Image(Long id, String image, Spot spot, Store store) { + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "guestbook_id") + private GuestBook guestBook; + + public Image(Long id, String image, ImageType imageType, Spot spot, Store store, GuestBook guestBook) { this.id = id; this.image = image; + this.imageType = imageType; this.spot = spot; this.store = store; + this.guestBook = guestBook; } public void updateImage(String image, Spot spot) { @@ -48,4 +60,9 @@ public void updateImage(String image, Store store) { this.image = image; this.store = store; } + + public void updateImage(String image, GuestBook guestBook) { + this.image = image; + this.guestBook = guestBook; + } } diff --git a/src/main/java/com/ttubeog/domain/image/domain/ImageType.java b/src/main/java/com/ttubeog/domain/image/domain/ImageType.java new file mode 100644 index 00000000..b143f3b3 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/domain/ImageType.java @@ -0,0 +1,10 @@ +package com.ttubeog.domain.image.domain; + +import lombok.Getter; + +@Getter +public enum ImageType { + SPOT, + STORE, + GUESTBOOK; +} diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java index 7964aff5..4ba09ee1 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.image.dto.request; +import com.ttubeog.domain.image.domain.ImageType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -10,7 +11,7 @@ public class CreateImageRequestDto { public String image; - public ImageRequestType imageRequestType; + public ImageType imageType; public Long placeId; } diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java b/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java deleted file mode 100644 index dff49fa5..00000000 --- a/src/main/java/com/ttubeog/domain/image/dto/request/ImageRequestType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ttubeog.domain.image.dto.request; - -public enum ImageRequestType { - SPOT, - STORE -} diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java index 795ed37d..c42b4c2b 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java @@ -1,5 +1,7 @@ package com.ttubeog.domain.image.dto.request; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.ImageType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -11,6 +13,6 @@ public class UpdateImageRequestDto { public Long id; public String image; - public ImageRequestType imageRequestType; + public ImageType imageType; public Long placeId; } diff --git a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java index 8570034c..88f61644 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java @@ -1,17 +1,20 @@ package com.ttubeog.domain.image.dto.response; -import com.ttubeog.domain.image.dto.request.ImageRequestType; +import com.ttubeog.domain.image.domain.ImageType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder @AllArgsConstructor +@NoArgsConstructor public class ImageResponseDto { public Long id; public String image; + public ImageType imageType; public Long placeId; } diff --git a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java new file mode 100644 index 00000000..d339b73f --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.image.exception; + +public class InvalidImageTypeException extends RuntimeException { + + public InvalidImageTypeException() { + super("올바르지 않은 이미지 타입입니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index e899d11a..e7b27f68 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -5,9 +5,9 @@ import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; -import com.ttubeog.domain.image.dto.request.ImageRequestType; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -111,7 +111,7 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques for (String s : imageList) { CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(s) - .imageRequestType(ImageRequestType.SPOT) + .imageType(ImageType.SPOT) .placeId(spot.getId()) .build(); imageService.createImage(createImageRequestDto); @@ -163,20 +163,23 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd spotRepository.save(spot); - /* - // 이미지 저장 - List imageList = updateSpotRequestDto.getImage(); - for (String s : imageList) { - UpdateImageRequestDto updateImageRequestDto = UpdateImageRequestDto.builder() + List imageList = imageRepository.findBySpotId(spotId); + + for (Image image : imageList) { + imageService.deleteImage(image.getId()); + } + + List imageStringList = updateSpotRequestDto.getImage(); + + for (String s : imageStringList) { + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(s) - .imageRequestType(ImageRequestType.SPOT) - .placeId(spot.getId()) + .imageType(ImageType.SPOT) + .placeId(spotId) .build(); - imageService.updateImage(updateImageRequestDto); + imageService.createImage(createImageRequestDto); } - */ - return getResponseEntity(spot); } From 3d16bb654598e3e30e68aa69af04936f2efd6170 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 07:13:25 +0900 Subject: [PATCH 203/356] =?UTF-8?q?[Chore]=20Likes=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=ED=99=95=EC=9D=B8=20=EB=B0=A9=EB=B2=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/likes/application/LikesService.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 9417c213..eb451b00 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.likes.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.likes.domain.Likes; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.likes.exception.AlreadyLikesException; @@ -15,6 +16,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -30,12 +32,14 @@ public class LikesService { private final StoreRepository storeRepository; private final SpotRepository spotRepository; private final LikesRepository likesRepository; + private final JwtTokenProvider jwtTokenProvider; // 매장 좋아요 누르기 @Transactional - public ResponseEntity likesStore(UserPrincipal userPrincipal, Long storeId) { + public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); if (likesRepository.existsByMemberIdAndStoreId(member.getId(), storeId)) { @@ -59,9 +63,10 @@ public ResponseEntity likesStore(UserPrincipal userPrincipal, Long storeId) { // 산책스팟 좋아요 누르기 @Transactional - public ResponseEntity likesSpot(UserPrincipal userPrincipal, Long spotId) { + public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(NonExistentSpotException::new); if (likesRepository.existsByMemberIdAndSpotId(member.getId(), spotId)) { From b4a6b3eafa83952d3ebef98eb69205424b28116e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 07:14:58 +0900 Subject: [PATCH 204/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/likes/application/LikesService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index eb451b00..4c61bc00 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -13,7 +13,6 @@ import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.domain.spot.exception.NonExistentSpotException; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; From e57a5f6c269c6fa7fbef14806a70b98d5af31f28 Mon Sep 17 00:00:00 2001 From: sanggae4133 Date: Fri, 9 Feb 2024 08:10:21 +0900 Subject: [PATCH 205/356] [Feat] add guestbook --- .../application/GuestBookService.java | 180 +++++++++++++++++- .../domain/guestbook/domain/GuestBook.java | 58 +++++- .../guestbook/domain/GuestBookType.java | 9 + .../dto/CreateGuestBookRequestDto.java | 4 - .../request/CreateGuestBookRequestDto.java | 23 +++ .../request/UpdateGuestBookRequestDto.java | 24 +++ .../dto/response/GuestBookResponseDto.java | 40 ++++ .../exception/InvalidGuestBookException.java | 9 + .../presentation/GuestBookController.java | 1 + .../domain/repository/ImageRepository.java | 2 + .../spot/presentation/SpotController.java | 2 +- 11 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java delete mode 100644 src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/guestbook/dto/request/UpdateGuestBookRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java create mode 100644 src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookException.java diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 56720b5a..acc59d1b 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,9 +1,35 @@ package com.ttubeog.domain.guestbook.application; -import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; -import com.ttubeog.global.config.security.token.UserPrincipal; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.guestbook.domain.GuestBook; +import com.ttubeog.domain.guestbook.domain.GuestBookType; +import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; +import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; +import com.ttubeog.domain.guestbook.dto.request.UpdateGuestBookRequestDto; +import com.ttubeog.domain.guestbook.dto.response.GuestBookResponseDto; +import com.ttubeog.domain.guestbook.exception.InvalidGuestBookException; +import com.ttubeog.domain.guestbook.exception.InvalidGuestBookIdException; +import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.ImageType; +import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; +import com.ttubeog.domain.image.exception.InvalidImageException; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; +import lombok.NonNull; import lombok.RequiredArgsConstructor; +import org.apache.ibatis.jdbc.Null; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -12,7 +38,155 @@ @Service @Transactional(readOnly = true) public class GuestBookService { + + private final GuestBookRepository guestBookRepository; + private final MemberRepository memberRepository; + private final SpotRepository spotRepository; + private final StoreRepository storeRepository; + private final ImageRepository imageRepository; + + private final ImageService imageService; + + private final JwtTokenProvider jwtTokenProvider; + + @NonNull + private ResponseEntity getResponseEntity(GuestBook guestBook) { + + GuestBookResponseDto guestBookResponseDto; + + if (guestBook.getGuestBookType().equals(GuestBookType.SPOT)) { + guestBookResponseDto = GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .spotId(guestBook.getSpot().getId()) + .memberId(guestBook.getMember().getId()) + .star(guestBook.getStar()) + .build(); + } else if (guestBook.getGuestBookType().equals(GuestBookType.STORE)) { + guestBookResponseDto = GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .storeId(guestBook.getStore().getId()) + .memberId(guestBook.getMember().getId()) + .star(guestBook.getStar()) + .build(); + } else { + throw new InvalidGuestBookException(); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(guestBookResponseDto) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + @Transactional public ResponseEntity createGuestBook(HttpServletRequest request, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { - return null; + + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + GuestBook guestBook; + + if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.SPOT)) { + Spot spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); + + guestBook = GuestBook.builder() + .member(member) + .spot(spot) + .guestBookType(createGuestBookRequestDto.getGuestBookType()) + .content(createGuestBookRequestDto.getContent()) + .star(createGuestBookRequestDto.getStar()) + .build(); + } else if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.STORE)) { + // TODO exception 교체 + Store store = storeRepository.findById(createGuestBookRequestDto.getStoreId()).orElseThrow(InvalidSpotIdException::new); + + guestBook = GuestBook.builder() + .member(member) + .store(store) + .guestBookType(createGuestBookRequestDto.getGuestBookType()) + .content(createGuestBookRequestDto.getContent()) + .star(createGuestBookRequestDto.getStar()) + .build(); + } else { + throw new InvalidGuestBookException(); + } + + guestBookRepository.save(guestBook); + + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + .image(createGuestBookRequestDto.getImage()) + .imageType(ImageType.GUESTBOOK) + .placeId(guestBook.getId()) + .build(); + imageService.createImage(createImageRequestDto); + + return getResponseEntity(guestBook); + } + + + public ResponseEntity findByGuestBookId(HttpServletRequest request, Long guestBookId) { + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); + + return getResponseEntity(guestBook); + } + + + @Transactional + public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestBookId, UpdateGuestBookRequestDto updateGuestBookRequestDto) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); + + Image image = imageRepository.findByGuestBookId(guestBook.getId()).orElseThrow(InvalidImageException::new); + + imageService.deleteImage(image.getId()); + + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + .image(updateGuestBookRequestDto.getImage()) + .imageType(ImageType.GUESTBOOK) + .placeId(guestBookId) + .build(); + + Image newImage = imageRepository.findById(imageService.createImage(createImageRequestDto).getId()).orElseThrow(InvalidImageException::new); + + guestBook.updateGuestBook(updateGuestBookRequestDto.getContent(), updateGuestBookRequestDto.getStar(), newImage); + + guestBookRepository.save(guestBook); + + return getResponseEntity(guestBook); + } + + @Transactional + public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestBookId) { + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); + + guestBookRepository.delete(guestBook); + + imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("방명록을 삭제했습니다").build()) + .build(); + + return ResponseEntity.ok(apiResponse); } } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java index b42c4d0c..4ce29296 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java @@ -1,17 +1,67 @@ package com.ttubeog.domain.guestbook.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter +@Builder @Entity +@Table(name = "guest_book") public class GuestBook extends BaseEntity { + @Schema(description = "방명록 ID", example = "1") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @Column(name = "guest_book_type", nullable = false) + private GuestBookType guestBookType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "spot_id") + private Spot spot; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + private String content; + + private Float star; + + @OneToOne(mappedBy = "guestBook", cascade = CascadeType.ALL) + private Image image; + + public GuestBook(Long id, Member member, GuestBookType guestBookType, Spot spot, Store store, String content, Float star, Image image) { + this.id = id; + this.member = member; + this.guestBookType = guestBookType; + this.spot = spot; + this.store = store; + this.content = content; + this.star = star; + this.image = image; + } + + public void updateGuestBook(String content, Float star, Image image) { + this.content = content; + this.star = star; + this.image = image; + } + } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java new file mode 100644 index 00000000..241c544b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.guestbook.domain; + +import lombok.Getter; + +@Getter +public enum GuestBookType { + SPOT, + STORE; +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java deleted file mode 100644 index 76b3fcc1..00000000 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/CreateGuestBookRequestDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.guestbook.dto; - -public class CreateGuestBookRequestDto { -} diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java new file mode 100644 index 00000000..c570c8ee --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java @@ -0,0 +1,23 @@ +package com.ttubeog.domain.guestbook.dto.request; + +import com.ttubeog.domain.guestbook.domain.GuestBookType; +import lombok.Getter; + +@Getter +public class CreateGuestBookRequestDto { + + private Long memberId; + + private GuestBookType guestBookType; + + private Long spotId; + + private Long storeId; + + private String content; + + private Float star; + + private String image; + +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/request/UpdateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/request/UpdateGuestBookRequestDto.java new file mode 100644 index 00000000..3e6c72a4 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/request/UpdateGuestBookRequestDto.java @@ -0,0 +1,24 @@ +package com.ttubeog.domain.guestbook.dto.request; + +import com.ttubeog.domain.guestbook.domain.GuestBookType; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +@Builder +public class UpdateGuestBookRequestDto { + + private String content; + + private Float star; + + private String image; + + public UpdateGuestBookRequestDto(String content, Float star, String image) { + this.content = content; + this.star = star; + this.image = image; + } +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java new file mode 100644 index 00000000..6f8e4495 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java @@ -0,0 +1,40 @@ +package com.ttubeog.domain.guestbook.dto.response; + +import com.ttubeog.domain.guestbook.domain.GuestBookType; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +public class GuestBookResponseDto { + + private Long id; + + private Long memberId; + + private GuestBookType guestBookType; + + private Long spotId; + + private Long storeId; + + private String content; + + private Float star; + + private String image; + + + public GuestBookResponseDto(Long id, Long memberId, GuestBookType guestBookType, Long spotId, Long storeId, String content, Float star, String image) { + this.id = id; + this.memberId = memberId; + this.guestBookType = guestBookType; + this.spotId = spotId; + this.storeId = storeId; + this.content = content; + this.star = star; + this.image = image; + } +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookException.java b/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookException.java new file mode 100644 index 00000000..36d7b7b7 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/guestbook/exception/InvalidGuestBookException.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.guestbook.exception; + +public class InvalidGuestBookException extends RuntimeException { + + public InvalidGuestBookException() { + super("방명록 타입과 장소 ID를 확인해주세요."); + } + +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 6c02b769..4b317aa3 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.guestbook.presentation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.RestController; @RestController diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java index 61c4a10d..844643da 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -16,4 +16,6 @@ public interface ImageRepository extends JpaRepository { List findBySpotId(Long id); List findByStoreId(Long id); + + Optional findByGuestBookId(Long id); } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 7b4ab26a..201c6ee0 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.guestbook.application.GuestBookService; -import com.ttubeog.domain.guestbook.dto.CreateGuestBookRequestDto; +import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.application.SpotService; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; From d87d8d0172d7ef5e6fbb51f2f77ac1d40a412f47 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 08:40:01 +0900 Subject: [PATCH 206/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/presentation/StoreController.java | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index b47f2938..31faf4b2 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.store.presentation; -<<<<<<< HEAD import com.ttubeog.domain.likes.application.LikesService; import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; @@ -10,26 +9,12 @@ import com.ttubeog.domain.store.dto.response.UpdateStoreRes; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -======= -import com.ttubeog.domain.store.application.StoreService; -import com.ttubeog.domain.store.dto.request.RegisterStoreReq; -import com.ttubeog.domain.store.dto.request.UpdateStoreReq; -import com.ttubeog.domain.store.dto.response.RegisterStoreRes; -import com.ttubeog.domain.store.dto.response.UpdateStoreRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; ->>>>>>> d24e682addba1c3f6ecb3d36471bc02b98fb1e09 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.tags.Tag; -<<<<<<< HEAD import jakarta.servlet.http.HttpServletRequest; -======= ->>>>>>> d24e682addba1c3f6ecb3d36471bc02b98fb1e09 import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -43,10 +28,8 @@ public class StoreController { private final StoreService storeService; -<<<<<<< HEAD private final LikesService likesService; -======= ->>>>>>> d24e682addba1c3f6ecb3d36471bc02b98fb1e09 + // 매장 등록 @Operation(summary = "매장 등록", description = "매장을 등록합니다.") @@ -56,17 +39,10 @@ public class StoreController { }) @PostMapping public ResponseEntity registerStore( -<<<<<<< HEAD HttpServletRequest request, @Valid @RequestBody RegisterStoreReq registerStoreReq ) { return storeService.registerStore(request, registerStoreReq); -======= - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody RegisterStoreReq registerStoreReq - ) { - return storeService.registerStore(userPrincipal, registerStoreReq); ->>>>>>> d24e682addba1c3f6ecb3d36471bc02b98fb1e09 } // 매장 수정 @@ -77,7 +53,6 @@ public ResponseEntity registerStore( }) @PatchMapping public ResponseEntity updateStore( -<<<<<<< HEAD HttpServletRequest request, @Valid @RequestBody UpdateStoreReq updateStoreReq ) { @@ -125,11 +100,4 @@ public ResponseEntity likesStore( ) { return likesService.likesStore(request, storeId); }*/ -======= - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, - @Valid @RequestBody UpdateStoreReq updateStoreReq - ) { - return storeService.updateStore(userPrincipal, updateStoreReq); - } ->>>>>>> d24e682addba1c3f6ecb3d36471bc02b98fb1e09 } From 87322f6f92ede49937f03f665756c5d7b7199279 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 08:40:47 +0900 Subject: [PATCH 207/356] =?UTF-8?q?[Feat]=20Store=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 765b4512..2533c136 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -47,6 +47,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .name(registerStoreReq.getName()) .info(registerStoreReq.getInfo()) .dongArea(dongArea) + .member(member) .detailAddress(registerStoreReq.getDetailAddress()) .latitude(registerStoreReq.getLatitude()) .longitude(registerStoreReq.getLongitude()) @@ -85,8 +86,8 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(updateStoreReq.getStoreId()).orElseThrow(NonExistentStoreException::new); - Member storeOwner = store.getMember(); - if (!storeOwner.getId().equals(memberId)) { + Long storeOwnerId = store.getMember().getId(); + if (!storeOwnerId.equals(memberId)) { throw new UnathorizedMemberException(); } From c78958fbcfa7f815b62540af8e1eefd000d1a7ad Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 18:32:09 +0900 Subject: [PATCH 208/356] =?UTF-8?q?[Fix]=20@Data=20annotation=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/dto/response/UpdateStoreRes.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java index 1b557760..263ead5e 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -3,7 +3,9 @@ import com.ttubeog.domain.store.domain.StoreType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; +import lombok.Data; +@Data public class UpdateStoreRes { @Schema(description = "매장 ID") From e3c72a27810cc63f9271b8b9bd0289e3d6befe56 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 19:08:46 +0900 Subject: [PATCH 209/356] =?UTF-8?q?[Feat]=20=EC=82=AD=EC=A0=9C=ED=95=98?= =?UTF-8?q?=EB=A0=A4=EB=8A=94=20=EC=9C=A0=EC=A0=80=EA=B0=80=20=EB=A7=A4?= =?UTF-8?q?=EC=9E=A5=20=EB=93=B1=EB=A1=9D=20=EC=9C=A0=EC=A0=80=EC=9D=B8?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 2533c136..28e132b2 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -125,6 +125,12 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + + Long storeOwnerId = store.getMember().getId(); + if (!storeOwnerId.equals(memberId)) { + throw new UnathorizedMemberException(); + } + storeRepository.delete(store); ApiResponse apiResponse = ApiResponse.builder() From 6d3a0e556d7d7d0990edf7eb86f7264b57b24e35 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 9 Feb 2024 23:12:19 +0900 Subject: [PATCH 210/356] =?UTF-8?q?Chore:=20Benefit-Game=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 안쓰는 파일 삭제 + 게임 수정 시 이미 저장된 benefit은 바뀌지 않게 수정 --- .../benefit/application/BenefitService.java | 128 ------------------ .../domain/benefit/domain/Benefit.java | 14 +- .../benefit/dto/request/CreateBenefitReq.java | 25 ---- .../benefit/dto/request/UpdateBenefitReq.java | 17 --- .../dto/response/CreateBenefitRes.java | 31 ----- .../benefit/dto/response/SaveBenefitRes.java | 5 - .../dto/response/UpdateBenefitRes.java | 32 ----- .../presentation/BenefitController.java | 63 --------- .../domain/game/application/GameService.java | 32 +++-- .../com/ttubeog/domain/game/domain/Game.java | 7 +- .../game/dto/request/CreateRouletteReq.java | 2 + .../game/dto/response/CreateRouletteRes.java | 2 + .../domain/game/dto/response/FindGameRes.java | 2 + .../dto/response/RouletteBenefitResDto.java | 7 + .../exception/OverlappingGameException.java | 7 - 15 files changed, 44 insertions(+), 330 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java delete mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java delete mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java delete mode 100644 src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java delete mode 100644 src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 618a753c..6d7640d8 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -5,30 +5,19 @@ import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; -import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; -import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; -import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; -import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; import com.ttubeog.domain.benefit.exception.AlreadyUsedBenefitException; import com.ttubeog.domain.benefit.exception.InvalidMemberBenefitException; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; -import com.ttubeog.domain.game.domain.Game; -import com.ttubeog.domain.game.domain.GameType; import com.ttubeog.domain.game.domain.repository.GameRepository; -import com.ttubeog.domain.game.dto.response.FindGameRes; -import com.ttubeog.domain.game.exception.NonExistentGameException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; -import com.ttubeog.global.payload.Message; -import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.hibernate.Hibernate; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; @@ -37,7 +26,6 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; @RequiredArgsConstructor @@ -51,84 +39,6 @@ public class BenefitService { private final MemberBenefitRepository memberBenefitRepository; private final GameRepository gameRepository; -// // 혜택 생성 -// @Transactional -// public ResponseEntity createBenefit(UserPrincipal userPrincipal, CreateBenefitReq createBenefitReq) throws JsonProcessingException { -// -// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); -// -//// Store store = storeRepository.findById(createBenefitReq.getStoreId()).orElseThrow(에러::new); -// -// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 -// -// Benefit benefit = Benefit.builder() -// .content(createBenefitReq.getContent()) -// .type(createBenefitReq.getType()) -//// .store(store) -// .build(); -// -// benefitRepository.save(benefit); -// -// CreateBenefitRes createBenefitRes = CreateBenefitRes.builder() -// .benefitId(benefit.getId()) -//// .storeId(benefit.getStore().getId()) -// .content(benefit.getContent()) -// .type(benefit.getType()) -// .build(); -// -// ApiResponse apiResponse = ApiResponse.builder() -// .check(true) -// .information(createBenefitRes) -// .build(); -// -// return ResponseEntity.ok(apiResponse); -// } - -// // 혜택 삭제 -// @Transactional -// public ResponseEntity deleteBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { -// -// Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); -// Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); -// -// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 -// -// benefitRepository.delete(benefit); -// -// ApiResponse apiResponse = ApiResponse.builder() -// .check(true) -// .information(Message.builder().message("혜택을 삭제했습니다.").build()) -// .build(); -// -// return ResponseEntity.ok(apiResponse); -// } - -// //혜택 수정 -// @Transactional -// public ResponseEntity updateBenefit(UserPrincipal userPrincipal, UpdateBenefitReq updateBenefitReq) throws JsonProcessingException { -// -// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); -// Benefit benefit = benefitRepository.findById(updateBenefitReq.getBenefitId()).orElseThrow(NonExistentBenefitException::new); -// -// //TODO Store의 등록유저가 현재 멤버와 일치하는지 확인 -// -// benefit.updateContent(updateBenefitReq.getContent()); -// -// UpdateBenefitRes updateBenefitRes = UpdateBenefitRes.builder() -// .benefitId(benefit.getId()) -// //.storeId(benefit.getStore().getId()) -// .content(benefit.getContent()) -// .type(benefit.getType()) -// .build(); -// -// ApiResponse apiResponse = ApiResponse.builder() -// .check(true) -// .information(updateBenefitRes) -// .build(); -// -// return ResponseEntity.ok(apiResponse); -// } - //게임 성공 후 혜택 저장 @Transactional public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { @@ -153,7 +63,6 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(benefit.getId()) -// .storeId(memberBenefit.getBenefit().getStore().getId()) .content(benefit.getContent()) .type(benefit.getType()) .used(memberBenefit.getUsed()) @@ -191,7 +100,6 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(benefit.getId()) -// .store(memberBenefit.store.getId()) .used(memberBenefit.getUsed()) .expried(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) @@ -218,7 +126,6 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page memberBenefit -> SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(memberBenefit.getBenefit().getId()) -// .store(memberBenefit.getStore().getId()) .used(memberBenefit.getUsed()) .expried(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) @@ -235,41 +142,6 @@ public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page return ResponseEntity.ok(apiResponse); } -// //혜택ID로 게임 조회 -// public ResponseEntity findGames(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { -// memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); -// Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); -// Game game = gameRepository.findByBenefit(benefit).orElseThrow(NonExistentGameException::new); -// -// List findGameResList = new ArrayList<>(); -// for (Game game : games) { -// FindGameRes.FindGameResBuilder builder = FindGameRes.builder() -// .gameId(game.getId()) -// .type(game.getType()); -// -// if (game.getType() == GameType.BASKETBALL) { -// builder.timeLimit(game.getBasketballGame().getTimeLimit()) -// .ballCount(game.getBasketballGame().getBallCount()) -// .successCount(game.getBasketballGame().getSuccessCount()); -// } else if (game.getType() == GameType.GIFT) { -// builder.timeLimit(game.getGiftGame().getTimeLimit()) -// .giftCount(game.getGiftGame().getGiftCount()); -// } else if (game.getType() == GameType.ROULETTE) { -// Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 -// builder.options(game.getRouletteGame().getOptions()); -// } -// -// findGameResList.add(builder.build()); -// } -// -// ApiResponse apiResponse = ApiResponse.builder() -// .check(true) -// .information(findGameResList) -// .build(); -// -// return ResponseEntity.ok(apiResponse); -// } - //한달지나면 expired true로 만들기 @Transactional @Scheduled(fixedRate = 60*60000) //1시간마다 검사 diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java index 02aa8fc7..c1105b1d 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/Benefit.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.game.domain.Game; +import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; import lombok.*; @@ -26,19 +27,16 @@ public class Benefit extends BaseEntity { @JoinColumn(name = "game_id") private Game game; -// @OneToMany(mappedBy = "benefit", cascade = CascadeType.ALL, orphanRemoval = true) -// private List game; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; @Builder - public Benefit(String content, BenefitType type, Game game) { + public Benefit(String content, BenefitType type, Game game, Store store) { this.content = content; this.type = type; this.game = game; - } - - public void updateBenefit(String content, BenefitType type) { - this.content = content; - this.type = type; + this.store = store; } public void deleteGame() { diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java deleted file mode 100644 index 85c307b0..00000000 --- a/src/main/java/com/ttubeog/domain/benefit/dto/request/CreateBenefitReq.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ttubeog.domain.benefit.dto.request; - -import com.ttubeog.domain.benefit.domain.BenefitType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigInteger; - -@Data -@Schema(description = "CreateBenefitRequest") -public class CreateBenefitReq { - -// @Schema(description = "매장 ID", example = "1") -// private Long storeId; - - @Schema(description = "게임 ID", example = "1") - private Long gameId; - - @Schema(description = "내용", example = "아메리카노 20% 할인") - private String content; - - @Schema(description = "혜택타입", example = "SALE") - private BenefitType type; - -} diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java b/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java deleted file mode 100644 index 52ea336a..00000000 --- a/src/main/java/com/ttubeog/domain/benefit/dto/request/UpdateBenefitReq.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.ttubeog.domain.benefit.dto.request; - -import com.ttubeog.domain.benefit.domain.BenefitType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Data -@Schema(description = "UpdateBenefitRequest") -public class UpdateBenefitReq { - - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; - - @Schema(description = "내용", example = "아메리카노 20% 할인") - private String content; - -} diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java deleted file mode 100644 index b2270541..00000000 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/CreateBenefitRes.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.ttubeog.domain.benefit.dto.response; - -import com.ttubeog.domain.benefit.domain.BenefitType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Data; - -@Data -public class CreateBenefitRes { - - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; - -// @Schema(description = "매장 ID", example = "1") -// private Long storeId; - - @Schema(description = "내용", example = "아메리카노 20% 할인") - private String content; - - @Schema(description = "혜택타입", example = "SALE") - private BenefitType type; - - @Builder -// public CreateBenefitRes(Long benefitId, Long storeId, String content, BenefitType type) { - public CreateBenefitRes(Long benefitId, String content, BenefitType type) { - this.benefitId = benefitId; -// this.storeId = storeId; - this.content = content; - this.type = type; - } -} diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java index 81cd9e1b..5005d763 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -16,9 +16,6 @@ public class SaveBenefitRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; -// @Schema(description = "매장 ID", example = "1") -// private Long storeId; - @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; @@ -35,11 +32,9 @@ public class SaveBenefitRes { private LocalDateTime createdAt; @Builder -// public SaveBenefitRes(Long id, Long benefitId, Long storeId, String content, BenefitType type, Boolean isUsed, Boolean expried, LocalDateTime createdAt) { public SaveBenefitRes(Long id, Long benefitId, String content, BenefitType type, Boolean used, Boolean expried, LocalDateTime createdAt) { this.id = id; this.benefitId = benefitId; -// this.storeId = storeId; this.content = content; this.type = type; this.used = used; diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java deleted file mode 100644 index 7883dc74..00000000 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/UpdateBenefitRes.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ttubeog.domain.benefit.dto.response; - -import com.ttubeog.domain.benefit.domain.BenefitType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Data; - -@Data -public class UpdateBenefitRes { - - @Schema(description = "혜택 ID", example = "1") - private Long benefitId; - -// @Schema(description = "매장 ID", example = "1") -// private Long storeId; - - @Schema(description = "내용", example = "아메리카노 20% 할인") - private String content; - - @Schema(description = "혜택타입", example = "SALE") - private BenefitType type; - - @Builder -// public CreateBenefitRes(Long benefitId, Long storeId, String content, BenefitType type) { - public UpdateBenefitRes(Long benefitId, String content, BenefitType type) { - this.benefitId = benefitId; -// this.storeId = storeId; - this.content = content; - this.type = type; - } - -} diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 77e1949b..df5b09f4 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -2,16 +2,10 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.application.BenefitService; -import com.ttubeog.domain.benefit.dto.request.CreateBenefitReq; -import com.ttubeog.domain.benefit.dto.request.UpdateBenefitReq; -import com.ttubeog.domain.benefit.dto.response.CreateBenefitRes; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; -import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; -import com.ttubeog.domain.game.dto.response.FindGameRes; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; -import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -20,7 +14,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import jakarta.validation.Valid; import org.springframework.web.bind.annotation.*; @Tag(name = "Benefit", description = "Benefit API") @@ -31,48 +24,6 @@ public class BenefitController { private final BenefitService benefitService; -// //혜택 생성 -// @Operation(summary = "혜택 생성", description = "매장의 혜택을 생성합니다.") -// @ApiResponses(value = { -// @ApiResponse(responseCode = "200", description = "혜택 생성 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CreateBenefitRes.class) ) } ), -// @ApiResponse(responseCode = "400", description = "혜택 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), -// }) -// @PostMapping -// public ResponseEntity createBenefit( -// @CurrentUser UserPrincipal userPrincipal, -// @Valid @RequestBody CreateBenefitReq createBenefitReq -// ) throws JsonProcessingException { -// return benefitService.createBenefit(userPrincipal, createBenefitReq); -// } - -// //혜택 삭제 -// @Operation(summary = "혜택 삭제", description = "매장의 혜택을 삭제합니다.") -// @ApiResponses(value = { -// @ApiResponse(responseCode = "200", description = "혜택 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), -// @ApiResponse(responseCode = "400", description = "혜택 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), -// }) -// @DeleteMapping("/{benefitId}") -// public ResponseEntity deleteBenefit( -// @CurrentUser UserPrincipal userPrincipal, -// @PathVariable(value = "benefitId") Long benefitId -// ) throws JsonProcessingException { -// return benefitService.deleteBenefit(userPrincipal, benefitId); -// } - - //혜택 수정 -// @Operation(summary = "혜택 수정", description = "매장의 혜택을 수정합니다.") -// @ApiResponses(value = { -// @ApiResponse(responseCode = "200", description = "혜택 수정 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UpdateBenefitRes.class) ) } ), -// @ApiResponse(responseCode = "400", description = "혜택 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), -// }) -// @PatchMapping -// public ResponseEntity updateBenefit( -// @CurrentUser UserPrincipal userPrincipal, -// @Valid @RequestBody UpdateBenefitReq updateBenefitReq -// ) throws JsonProcessingException { -// return benefitService.updateBenefit(userPrincipal, updateBenefitReq); -// } - //게임 성공 후 혜택 저장 @Operation(summary = "혜택 저장", description = "게임 성공 후 혜택을 저장합니다.") @ApiResponses(value = { @@ -114,18 +65,4 @@ public ResponseEntity findMyBenefit( ) throws JsonProcessingException { return benefitService.findMyBenefit(userPrincipal, page); } - -// //혜택으로 모든 게임 조회 -// @Operation(summary = "혜택으로 게임 조회", description = "혜택에 해당하는 게임을 모두 조회합니다. 최대 3개입니다.") -// @ApiResponses(value = { -// @ApiResponse(responseCode = "200", description = "게임 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), -// @ApiResponse(responseCode = "400", description = "게임 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), -// }) -// @GetMapping("/{benefitId}/game") -// public ResponseEntity findGames( -// @CurrentUser UserPrincipal userPrincipal, -// @PathVariable(value = "benefitId") Long benefitId -// ) throws JsonProcessingException { -// return benefitService.findGames(userPrincipal, benefitId); -// } } diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 07459327..4b83717c 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -45,6 +45,8 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + //TODO 연결 후 store에 이미 존재하는 gametype인지 확인 + Game game = Game.builder() .type(GameType.GIFT) .build(); @@ -187,18 +189,25 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); + benefit.deleteGame(); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); giftGame.updateGiftCount(updateGiftReq.getGiftCount()); - benefit.updateBenefit(updateGiftReq.getBenefitContent(), updateGiftReq.getBenefitType()); + + Benefit newBenefit = Benefit.builder() + .game(giftGame.getGame()) + .type(updateGiftReq.getBenefitType()) + .content(updateGiftReq.getBenefitContent()) + .build(); + benefitRepository.save(newBenefit); UpdateGiftRes updateGiftRes = UpdateGiftRes.builder() .gameId(giftGame.getId()) .giftCount(giftGame.getGiftCount()) .timeLimit(giftGame.getTimeLimit()) - .benefitId(benefit.getId()) - .benefitContent(benefit.getContent()) - .benefitType(benefit.getType()) + .benefitId(newBenefit.getId()) + .benefitContent(newBenefit.getContent()) + .benefitType(newBenefit.getType()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -216,20 +225,27 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); + benefit.deleteGame(); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); basketballGame.updateTimeLimit(updateBasketballReq.getTimeLimit()); - benefit.updateBenefit(updateBasketballReq.getBenefitContent(), updateBasketballReq.getBenefitType()); + + Benefit newBenefit = Benefit.builder() + .game(basketballGame.getGame()) + .type(updateBasketballReq.getBenefitType()) + .content(updateBasketballReq.getBenefitContent()) + .build(); + benefitRepository.save(newBenefit); UpdateBasketballRes updateBasketballRes = UpdateBasketballRes.builder() .gameId(basketballGame.getId()) .ballCount(basketballGame.getBallCount()) .timeLimit(basketballGame.getTimeLimit()) .successCount(basketballGame.getSuccessCount()) - .benefitId(benefit.getId()) - .benefitContent(benefit.getContent()) - .benefitType(benefit.getType()) + .benefitId(newBenefit.getId()) + .benefitContent(newBenefit.getContent()) + .benefitType(newBenefit.getType()) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/game/domain/Game.java b/src/main/java/com/ttubeog/domain/game/domain/Game.java index e84376df..2c1edd03 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/Game.java +++ b/src/main/java/com/ttubeog/domain/game/domain/Game.java @@ -23,10 +23,6 @@ public class Game extends BaseEntity { @Enumerated(EnumType.STRING) private GameType type; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "store_id") - private Store store; - @OneToOne(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) private GiftGame giftGame; @@ -37,8 +33,7 @@ public class Game extends BaseEntity { private RouletteGame rouletteGame; @Builder - public Game(GameType type, Store store) { + public Game(GameType type) { this.type = type; - this.store = store; } } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java index 4f3d1d68..5393fe6e 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java @@ -10,6 +10,8 @@ @Schema(description = "CreateRouletteGameRequest") public class CreateRouletteReq { + //private Long storeId + @Schema(description = "혜택 타입", example = "SALE") private BenefitType benefitType; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java index e4ba9ac8..5c9eb32c 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -15,6 +15,8 @@ public class CreateRouletteRes { @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; + //private Long storeId; + private List benefits; @Builder diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 9e5cb8f1..67afa7f7 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -14,6 +14,8 @@ public class FindGameRes { @Schema(description = "게임 ID", example = "1") private Long gameId; + //private Long storeId; + @Schema(description = "종류", example = "roulette") private GameType type; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java b/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java index 75672734..1fb0fd78 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java @@ -1,16 +1,23 @@ package com.ttubeog.domain.game.dto.response; import com.ttubeog.domain.benefit.domain.BenefitType; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @Data public class RouletteBenefitResDto { + + @Schema(description = "혜택 Id", example = "1") private Long benefitId; + + @Schema(description = "혜택 내용", example = "아메리카노 20% 할인") private String content; + + @Schema(description = "혜택 타입", example = "SALE") private BenefitType type; @Builder diff --git a/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java b/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java deleted file mode 100644 index ec10296b..00000000 --- a/src/main/java/com/ttubeog/domain/game/exception/OverlappingGameException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.game.exception; - -public class OverlappingGameException extends RuntimeException { - - public OverlappingGameException() { - super("하나의 혜택에 같은 종류의 게임은 저장할 수 없습니다.");} -} From 5425943c888d498567dc614fa07c09055f08ba69 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:15:11 +0900 Subject: [PATCH 211/356] =?UTF-8?q?Chore:=20build.gradle=20=EC=9B=90?= =?UTF-8?q?=EC=83=81=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 05608c45..bc8c1b97 100644 --- a/build.gradle +++ b/build.gradle @@ -30,9 +30,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" -// runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' - + runtimeOnly 'com.mysql:mysql-connector-j' + testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } From 02b9a477c9daf54bb974b3293e94e99f94e4ee75 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:18:31 +0900 Subject: [PATCH 212/356] =?UTF-8?q?Chore:=20Update=20BenefitService=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=EC=9C=A0=EC=A0=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 6d7640d8..539a6aaa 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -1,6 +1,8 @@ package com.ttubeog.domain.benefit.application; import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; @@ -38,12 +40,13 @@ public class BenefitService { private final StoreRepository storeRepository; private final MemberBenefitRepository memberBenefitRepository; private final GameRepository gameRepository; + private final JwtTokenProvider jwtTokenProvider; //게임 성공 후 혜택 저장 @Transactional - public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 @@ -81,9 +84,9 @@ public ResponseEntity saveBenefit(UserPrincipal userPrincipal, Long benefitId //혜택 사용 @Transactional - public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); //만료기간 안에 혜택은 오직 한개 @@ -116,9 +119,9 @@ public ResponseEntity useBenefit(UserPrincipal userPrincipal, Long benefitId) } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ResponseEntity findMyBenefit(UserPrincipal userPrincipal, Integer page) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Page memberBenefitPage = memberBenefitRepository.findAllByMember(member, PageRequest.of(page, 10)); @@ -157,4 +160,4 @@ public void autoCheckExpired() { } } } -} \ No newline at end of file +} From 4e9bc6eb31d4934e24d6be5988651b290b7cbb8f Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:26:50 +0900 Subject: [PATCH 213/356] =?UTF-8?q?Chore:=20Update=20BenefitController=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EC=9C=A0=EC=A0=80=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/presentation/BenefitController.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index df5b09f4..44d310fb 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -12,6 +12,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -32,10 +33,10 @@ public class BenefitController { }) @PatchMapping("/{benefitId}") public ResponseEntity saveBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.saveBenefit(userPrincipal, benefitId); + return benefitService.saveBenefit(request, benefitId); } //혜택 사용 @@ -46,10 +47,10 @@ public ResponseEntity saveBenefit( }) @PatchMapping("{benefitId}/use") public ResponseEntity useBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.useBenefit(userPrincipal, benefitId); + return benefitService.useBenefit(request, benefitId); } //혜택 조회 @@ -60,9 +61,9 @@ public ResponseEntity useBenefit( }) @GetMapping public ResponseEntity findMyBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { - return benefitService.findMyBenefit(userPrincipal, page); + return benefitService.findMyBenefit(request, page); } } From 673c77be0ab7b867b803758bcc766e5894072dea Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:38:09 +0900 Subject: [PATCH 214/356] =?UTF-8?q?Chore:=20Update=20GameController=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=EC=9C=A0=EC=A0=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/presentation/GameController.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index a3e393d4..db4d4f36 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -35,10 +36,10 @@ public class GameController { }) @PostMapping("/gift") public ResponseEntity createGift( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateGiftReq createGiftReq ) throws JsonProcessingException { - return gameService.createGift(userPrincipal, createGiftReq); + return gameService.createGift(request, createGiftReq); } //농구 게임 생성 @@ -49,10 +50,10 @@ public ResponseEntity createGift( }) @PostMapping("/basketball") public ResponseEntity createBasketball( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateBasketballReq createBasketballReq ) throws JsonProcessingException { - return gameService.createBasketBall(userPrincipal, createBasketballReq); + return gameService.createBasketBall(request, createBasketballReq); } //돌림판 게임 생성 @@ -63,10 +64,10 @@ public ResponseEntity createBasketball( }) @PostMapping("/roulette") public ResponseEntity createRoulette( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody CreateRouletteReq createRouletteReq ) throws JsonProcessingException { - return gameService.createRoulette(userPrincipal, createRouletteReq); + return gameService.createRoulette(request, createRouletteReq); } //선물 게임 수정 @@ -77,10 +78,10 @@ public ResponseEntity createRoulette( }) @PatchMapping("/gift") public ResponseEntity updateGift( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateGiftReq updateGiftReq ) throws JsonProcessingException { - return gameService.updateGift(userPrincipal, updateGiftReq); + return gameService.updateGift(request, updateGiftReq); } //농구 게임 수정 @@ -91,10 +92,10 @@ public ResponseEntity updateGift( }) @PatchMapping("/basketball") public ResponseEntity updateBasketball( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateBasketballReq updateBasketballReq ) throws JsonProcessingException { - return gameService.updateBasketball(userPrincipal, updateBasketballReq); + return gameService.updateBasketball(request, updateBasketballReq); } //돌림판 게임 수정 @@ -105,10 +106,10 @@ public ResponseEntity updateBasketball( }) @PatchMapping("/roulette") public ResponseEntity updateRoulette( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateRouletteReq updateRouletteReq ) throws JsonProcessingException { - return gameService.updateRoulette(userPrincipal, updateRouletteReq); + return gameService.updateRoulette(request, updateRouletteReq); } //게임 삭제 @@ -119,10 +120,10 @@ public ResponseEntity updateRoulette( }) @DeleteMapping("/{gameId}") public ResponseEntity deleteGame( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.deleteGame(userPrincipal, gameId); + return gameService.deleteGame(request, gameId); } //게임 조회 @@ -133,10 +134,10 @@ public ResponseEntity deleteGame( }) @GetMapping("/{gameId}") public ResponseEntity findGame( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.findGame(userPrincipal, gameId); + return gameService.findGame(request, gameId); } //게임 조회 @@ -147,10 +148,10 @@ public ResponseEntity findGame( }) @GetMapping("/{gameId}/benefit") public ResponseEntity findBenefit( - @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.findBenefit(userPrincipal, gameId); + return gameService.findBenefit(request, gameId); } } From 7e081b23e18344f014885115d1e107e2f2e974a8 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Sat, 10 Feb 2024 01:10:56 +0900 Subject: [PATCH 215/356] =?UTF-8?q?Chore:=20Update=20GameService=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=EC=9C=A0=EC=A0=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 4b83717c..deccfe33 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -1,6 +1,8 @@ package com.ttubeog.domain.game.application; import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; @@ -38,12 +40,13 @@ public class GameService { private final BasketBallRepository basketBallRepository; private final RouletteRepository rouletteRepository; private final MemberBenefitRepository memberBenefitRepository; + private final JwtTokenProvider jwtTokenProvider; // 선물게임 생성 @Transactional - public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq createGiftReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); //TODO 연결 후 store에 이미 존재하는 gametype인지 확인 @@ -88,9 +91,9 @@ public ResponseEntity createGift(UserPrincipal userPrincipal, CreateGiftReq c // 농구게임 생성 @Transactional - public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBasketballReq createBasketballReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = Game.builder() .type(GameType.BASKETBALL) @@ -135,9 +138,9 @@ public ResponseEntity createBasketBall(UserPrincipal userPrincipal, CreateBas //돌림판 게임 생성 @Transactional - public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRouletteReq createRouletteReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = Game.builder() .type(GameType.ROULETTE) @@ -184,9 +187,9 @@ public ResponseEntity createRoulette(UserPrincipal userPrincipal, CreateRoule //선물게임 수정 @Transactional - public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq updateGiftReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); @@ -220,9 +223,9 @@ public ResponseEntity updateGift(UserPrincipal userPrincipal, UpdateGiftReq u //농구게임 수정 @Transactional - public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); @@ -258,9 +261,9 @@ public ResponseEntity updateBasketball(UserPrincipal userPrincipal, UpdateBas //돌림판 게임 수정 @Transactional - public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(rouletteGame.getGame()); benefitList.forEach(benefit -> benefit.deleteGame()); @@ -301,9 +304,9 @@ public ResponseEntity updateRoulette(UserPrincipal userPrincipal, UpdateRoule //게임 삭제 @Transactional - public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity deleteGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(game); List memberBenefitList = memberBenefitRepository.findAllByMemberAndBenefitIn(member, benefitList); @@ -322,9 +325,9 @@ public ResponseEntity deleteGame(UserPrincipal userPrincipal, Long gameId) th //게임 조회 @Transactional - public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); FindGameRes.FindGameResBuilder builder = FindGameRes.builder() @@ -355,9 +358,9 @@ public ResponseEntity findGame(UserPrincipal userPrincipal, Long gameId) thro //게임ID로 혜택 조회 @Transactional - public ResponseEntity findBenefit(UserPrincipal userPrincipal, Long gameId) throws JsonProcessingException { - - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(game); From 5d304c4392516b120891d839f33d60d7640f696e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 10 Feb 2024 17:44:42 +0900 Subject: [PATCH 216/356] =?UTF-8?q?[Feat]=20Store=20=EB=93=B1=EB=A1=9D,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=20stars=EA=B0=92=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/store/application/StoreService.java | 5 ++++- .../domain/store/dto/response/RegisterStoreRes.java | 8 ++++++-- .../ttubeog/domain/store/dto/response/UpdateStoreRes.java | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 28e132b2..de21488a 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -52,6 +52,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .latitude(registerStoreReq.getLatitude()) .longitude(registerStoreReq.getLongitude()) .image(registerStoreReq.getImage()) + .stars(0.0f) .type(registerStoreReq.getType()) .build(); @@ -67,6 +68,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .latitude(store.getLatitude()) .longitude(store.getLongitude()) .image(store.getImage()) + .stars(store.getStars()) .type(store.getType()) .build(); @@ -107,6 +109,7 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq .latitude(store.getLatitude()) .longitude(store.getLongitude()) .image(store.getImage()) + .stars(store.getStars()) .type(store.getType()) .build(); @@ -176,4 +179,4 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI return ResponseEntity.ok(apiResponse); } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java index 622a8660..bc679733 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -36,12 +36,15 @@ public class RegisterStoreRes { @Schema(description = "이미지") private String image; + @Schema(description = "평균 별점") + private Float stars; + @Schema(description = "업종") private StoreType type; @Builder public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, - String detailAddress,Float latitude, Float longitude, String image, StoreType type) { + String detailAddress,Float latitude, Float longitude, String image, Float stars, StoreType type) { this.storeId = storeId; this.memberId = memberId; this.name = name; @@ -51,6 +54,7 @@ public RegisterStoreRes(Long storeId, Long memberId, String name, String info, L this.latitude = latitude; this.longitude = longitude; this.image = image; + this.stars = stars; this.type = type; } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java index 263ead5e..093f64d6 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -29,12 +29,15 @@ public class UpdateStoreRes { @Schema(description = "이미지") private String image; + @Schema(description = "평균 별점") + private Float stars; + @Schema(description = "업종") private StoreType type; @Builder public UpdateStoreRes(Long storeId, String detailAddress, String name, String info, - Float latitude, Float longitude, String image, StoreType type) { + Float latitude, Float longitude, String image, Float stars, StoreType type) { this.storeId = storeId; this.detailAddress = detailAddress; this.name = name; @@ -42,6 +45,7 @@ public UpdateStoreRes(Long storeId, String detailAddress, String name, String in this.latitude = latitude; this.longitude = longitude; this.image = image; + this.stars = stars; this.type = type; } } From 0c7bf744fe15c864285e148483439b00cf39b6ec Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 10 Feb 2024 18:09:57 +0900 Subject: [PATCH 217/356] =?UTF-8?q?[Refac]=20=EC=9C=84=EB=8F=84,=20?= =?UTF-8?q?=EA=B2=BD=EB=8F=84=20=ED=83=80=EC=9E=85=20Double=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/store/domain/Store.java | 8 ++++---- .../domain/store/dto/request/RegisterStoreReq.java | 4 ++-- .../ttubeog/domain/store/dto/request/UpdateStoreReq.java | 4 ++-- .../domain/store/dto/response/GetStoreDetailRes.java | 4 ++-- .../domain/store/dto/response/RegisterStoreRes.java | 6 +++--- .../ttubeog/domain/store/dto/response/UpdateStoreRes.java | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 4229683a..44d96fc0 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -28,10 +28,10 @@ public class Store extends BaseEntity { private String detailAddress; @Column(name = "latitude") - private Float latitude; + private Double latitude; @Column(name = "longitude") - private Float longitude; + private Double longitude; @Column(name = "image") private String image; @@ -63,11 +63,11 @@ public void updateDetailAddress(String detailAddress) { this.detailAddress = detailAddress; } - public void updateLatitude(Float latitude) { + public void updateLatitude(Double latitude) { this.latitude = latitude; } - public void updateLongitude(Float longitude) { + public void updateLongitude(Double longitude) { this.longitude = longitude; } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java index e7f8ca18..709981fb 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java +++ b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java @@ -21,10 +21,10 @@ public class RegisterStoreReq { private String detailAddress; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "이미지") private String image; diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java index 40e5bdba..10eb30a0 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java +++ b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java @@ -20,10 +20,10 @@ public class UpdateStoreReq { private String detailAddress; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "이미지") private String image; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index 0569082b..1716853d 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -33,10 +33,10 @@ public class GetStoreDetailRes { private String detailAddress; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "이미지") private String image; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java index bc679733..9c1f27a1 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -28,10 +28,10 @@ public class RegisterStoreRes { private String detailAddress; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "이미지") private String image; @@ -44,7 +44,7 @@ public class RegisterStoreRes { @Builder public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, - String detailAddress,Float latitude, Float longitude, String image, Float stars, StoreType type) { + String detailAddress, Double latitude, Double longitude, String image, Float stars, StoreType type) { this.storeId = storeId; this.memberId = memberId; this.name = name; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java index 093f64d6..5fdc576b 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -21,10 +21,10 @@ public class UpdateStoreRes { private String detailAddress; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "이미지") private String image; @@ -37,7 +37,7 @@ public class UpdateStoreRes { @Builder public UpdateStoreRes(Long storeId, String detailAddress, String name, String info, - Float latitude, Float longitude, String image, Float stars, StoreType type) { + Double latitude, Double longitude, String image, Float stars, StoreType type) { this.storeId = storeId; this.detailAddress = detailAddress; this.name = name; From 25349d1216c3af1e2d0ced84bb67251ba79c2d9f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 10 Feb 2024 18:13:46 +0900 Subject: [PATCH 218/356] =?UTF-8?q?[Chore]=20ENUM=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=8C=80=EB=AC=B8=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/store/domain/StoreType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/domain/StoreType.java b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java index cb90e878..8ee1fc5c 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/StoreType.java +++ b/src/main/java/com/ttubeog/domain/store/domain/StoreType.java @@ -1,5 +1,5 @@ package com.ttubeog.domain.store.domain; public enum StoreType { - restaurant, cafe + RESTAURANT, CAFE } From c1e3825283d1ba33b37653d562375013323d376e Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Sun, 11 Feb 2024 01:15:46 +0900 Subject: [PATCH 219/356] =?UTF-8?q?Chore:=20BenefitController=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/benefit/presentation/BenefitController.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 9975165b..88b7a03a 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -3,11 +3,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.application.BenefitService; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; -import com.ttubeog.domain.benefit.dto.response.UpdateBenefitRes; -import com.ttubeog.domain.game.dto.response.FindGameRes; -import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; From 6a9af1ee291fdaf78e7485eec9f33956bb525f5e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 11 Feb 2024 02:14:44 +0900 Subject: [PATCH 220/356] =?UTF-8?q?[Feat]=20Store=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=A0=80=EC=9E=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/application/ImageService.java | 12 ++-- .../store/application/StoreService.java | 63 +++++++++++++++++-- .../ttubeog/domain/store/domain/Store.java | 8 +-- .../store/dto/request/RegisterStoreReq.java | 6 +- .../store/dto/request/UpdateStoreReq.java | 6 +- .../store/dto/response/GetStoreDetailRes.java | 4 +- .../store/dto/response/RegisterStoreRes.java | 8 ++- .../store/dto/response/UpdateStoreRes.java | 8 ++- .../exception/InvalidStoreIdException.java | 8 +++ 9 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index 47479dd9..5ff0d528 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -13,6 +13,7 @@ import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.InvalidStoreIdException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -92,7 +93,7 @@ public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) image = Image.builder() .image(createImageRequestDto.getImage()) .imageType(createImageRequestDto.getImageType()) - .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidStoreIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() @@ -104,13 +105,13 @@ public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) image = Image.builder() .image(createImageRequestDto.getImage()) .imageType(createImageRequestDto.getImageType()) - .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) + .guestBook(guestBookRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidGuestBookIdException::new)) .build(); imageResponseDto = ImageResponseDto.builder() .id(image.getId()) .imageType(image.getImageType()) - .placeId(image.getStore().getId()) + .placeId(image.getGuestBook().getId()) .build(); } else { throw new InvalidImageTypeException(); @@ -143,8 +144,7 @@ public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) .placeId(image.getSpot().getId()) .build(); } else if (updateImageRequestDto.getImageType().equals(ImageType.STORE)){ - // TODO 스토어 exception 수정하기 - image.updateImage(updateImageRequestDto.getImage(), storeRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + image.updateImage(updateImageRequestDto.getImage(), storeRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidStoreIdException::new)); imageResponseDto = ImageResponseDto.builder() .id(image.getId()) @@ -157,7 +157,7 @@ public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) imageResponseDto = ImageResponseDto.builder() .id(image.getId()) .imageType(image.getImageType()) - .placeId(image.getStore().getId()) + .placeId(image.getGuestBook().getId()) .build(); } else { throw new InvalidImageTypeException(); diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index de21488a..96b646c4 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -3,8 +3,14 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.image.domain.ImageType; +import com.ttubeog.domain.image.domain.repository.ImageRepository; +import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; @@ -24,6 +30,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + +import static com.ttubeog.domain.image.application.ImageService.getImageString; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -32,6 +42,8 @@ public class StoreService { private final StoreRepository storeRepository; private final MemberRepository memberRepository; private final DongAreaRepository dongAreaRepository; + private final ImageRepository imageRepository; + private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; // 매장 등록 @@ -43,6 +55,10 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore DongArea dongArea = dongAreaRepository.findById(registerStoreReq.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); + if (registerStoreReq.getImage().isEmpty() || registerStoreReq.getImage().size() > 10) { + throw new InvalidImageListSizeException(); + } + Store store = Store.builder() .name(registerStoreReq.getName()) .info(registerStoreReq.getInfo()) @@ -51,13 +67,23 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .detailAddress(registerStoreReq.getDetailAddress()) .latitude(registerStoreReq.getLatitude()) .longitude(registerStoreReq.getLongitude()) - .image(registerStoreReq.getImage()) .stars(0.0f) .type(registerStoreReq.getType()) .build(); storeRepository.save(store); + // 이미지 저장 + List imageList = registerStoreReq.getImage(); + for (String s : imageList) { + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + .image(s) + .imageType(ImageType.SPOT) + .placeId(store.getId()) + .build(); + imageService.createImage(createImageRequestDto); + } + RegisterStoreRes registerStoreRes = RegisterStoreRes.builder() .storeId(store.getId()) .memberId(member.getId()) @@ -67,7 +93,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(store.getImage()) + .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) .build(); @@ -93,14 +119,36 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq throw new UnathorizedMemberException(); } + if (updateStoreReq.getImage().isEmpty() || updateStoreReq.getImage().size() > 10) { + throw new InvalidImageListSizeException(); + } + store.updateName(updateStoreReq.getName()); store.updateInfo(updateStoreReq.getInfo()); store.updateDetailAddress(updateStoreReq.getDetailAddress()); store.updateLatitude(updateStoreReq.getLatitude()); store.updateLongitude(updateStoreReq.getLongitude()); - store.updateImage(updateStoreReq.getImage()); store.updateType(updateStoreReq.getType()); + storeRepository.save(store); + + List imageList = imageRepository.findByStoreId(store.getId()); + + for (Image image : imageList) { + imageService.deleteImage(image.getId()); + } + + List imageStringList = updateStoreReq.getImage(); + + for (String s : imageStringList) { + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() + .image(s) + .imageType(ImageType.SPOT) + .placeId(store.getId()) + .build(); + imageService.createImage(createImageRequestDto); + } + UpdateStoreRes updateStoreRes = UpdateStoreRes.builder() .storeId(store.getId()) .name(store.getName()) @@ -108,7 +156,7 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(store.getImage()) + .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) .build(); @@ -136,6 +184,11 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { storeRepository.delete(store); + List imageList = imageRepository.findByStoreId(store.getId()); + for (Image image : imageList) { + imageService.deleteImage(image.getId()); + } + ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) @@ -164,7 +217,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(store.getImage()) + .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) //.storeBenefits(storeBenefits.stream().map(BenefitType::getType).collect(Collectors.toList())) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 44d96fc0..4f9ec52c 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -33,9 +33,6 @@ public class Store extends BaseEntity { @Column(name = "longitude") private Double longitude; - @Column(name = "image") - private String image; - @Column(name = "stars") private Float stars; @@ -71,10 +68,7 @@ public void updateLongitude(Double longitude) { this.longitude = longitude; } - public void updateImage(String image) { - this.image = image; - } - + public void updateStars(Float stars) { this.stars = stars; } public void updateType(StoreType type) { this.type = type; } diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java index 709981fb..a238766a 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java +++ b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data @Schema(description = "매장 등록 Request") public class RegisterStoreReq { @@ -26,8 +28,8 @@ public class RegisterStoreReq { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지") - private String image; + @Schema(description = "이미지 리스트") + private List image; @Schema(description = "업종") private StoreType type; diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java index 10eb30a0..f998fcda 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java +++ b/src/main/java/com/ttubeog/domain/store/dto/request/UpdateStoreReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data public class UpdateStoreReq { @@ -25,8 +27,8 @@ public class UpdateStoreReq { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지") - private String image; + @Schema(description = "이미지 리스트") + private List image; @Schema(description = "업종") private StoreType type; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index 1716853d..6f6ac466 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -38,8 +38,8 @@ public class GetStoreDetailRes { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지") - private String image; + @Schema(description = "이미지 리스트") + private List image; @Schema(description = "별점") private Float stars; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java index 9c1f27a1..c8222f49 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.util.List; + @Data @Schema(description = "매장 등록 Response") public class RegisterStoreRes { @@ -33,8 +35,8 @@ public class RegisterStoreRes { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지") - private String image; + @Schema(description = "이미지 리스트") + private List image; @Schema(description = "평균 별점") private Float stars; @@ -44,7 +46,7 @@ public class RegisterStoreRes { @Builder public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, - String detailAddress, Double latitude, Double longitude, String image, Float stars, StoreType type) { + String detailAddress, Double latitude, Double longitude, List image, Float stars, StoreType type) { this.storeId = storeId; this.memberId = memberId; this.name = name; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java index 5fdc576b..4cf51971 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/UpdateStoreRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.util.List; + @Data public class UpdateStoreRes { @@ -26,8 +28,8 @@ public class UpdateStoreRes { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지") - private String image; + @Schema(description = "이미지 리스트") + private List image; @Schema(description = "평균 별점") private Float stars; @@ -37,7 +39,7 @@ public class UpdateStoreRes { @Builder public UpdateStoreRes(Long storeId, String detailAddress, String name, String info, - Double latitude, Double longitude, String image, Float stars, StoreType type) { + Double latitude, Double longitude, List image, Float stars, StoreType type) { this.storeId = storeId; this.detailAddress = detailAddress; this.name = name; diff --git a/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java b/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java new file mode 100644 index 00000000..c612df13 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.store.exception; + +public class InvalidStoreIdException extends RuntimeException { + + public InvalidStoreIdException() { + super("존재하지 않는 매장 Id값입니다."); + } +} \ No newline at end of file From 910e1bc125481a958e22e03c85c95d7cf28e4e84 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 11 Feb 2024 02:39:19 +0900 Subject: [PATCH 221/356] =?UTF-8?q?[Remove]=20LikesController=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/likes/presentation/LikesController.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/likes/presentation/LikesController.java diff --git a/src/main/java/com/ttubeog/domain/likes/presentation/LikesController.java b/src/main/java/com/ttubeog/domain/likes/presentation/LikesController.java deleted file mode 100644 index f4b136a3..00000000 --- a/src/main/java/com/ttubeog/domain/likes/presentation/LikesController.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.likes.presentation; - -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class LikesController { -} From 0be455dc794693d2cef0723508b248ddfe1f59a1 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 11 Feb 2024 03:04:26 +0900 Subject: [PATCH 222/356] =?UTF-8?q?[Refac]=20=EC=9C=84=EB=8F=84,=20?= =?UTF-8?q?=EA=B2=BD=EB=8F=84=20=ED=83=80=EC=9E=85=20Double=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/place/application/PlaceService.java | 6 +++--- .../ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java | 4 ++-- .../ttubeog/domain/place/dto/response/GetAllPlaceRes.java | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 33483e9f..e888c963 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -172,7 +172,7 @@ public ResponseEntity getAllPlacesRecommended(Pageable pageable) { return ResponseEntity.ok(apiResponse); } - private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + private double calculateDistance(Double lat1, Double lon1, Double lat2, Double lon2) { double R = 6371; // 지구 반지름 double dLat = Math.toRadians(lat2 - lat1); @@ -196,8 +196,8 @@ public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq, memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); List allPlaces = getAllPlaceResList(pageable); - Float userLatitude = getNearbyPlaceReq.getLatitude(); - Float userLongitude = getNearbyPlaceReq.getLongitude(); + Double userLatitude = getNearbyPlaceReq.getLatitude(); + Double userLongitude = getNearbyPlaceReq.getLongitude(); for (GetAllPlaceRes place: allPlaces) { double distance = calculateDistance(userLatitude, userLongitude, place.getLatitude(), place.getLongitude()); diff --git a/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java b/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java index e60849ca..5954f6c0 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java +++ b/src/main/java/com/ttubeog/domain/place/dto/request/GetNearbyPlaceReq.java @@ -7,8 +7,8 @@ public class GetNearbyPlaceReq { @Schema(description = "사용자 위치 위도값") - private Float latitude; + private Double latitude; @Schema(description = "사용자 위치 경도값") - private Float longitude; + private Double longitude; } diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index 928e4f74..c21c3d01 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -23,10 +23,10 @@ public class GetAllPlaceRes { private String name; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Schema(description = "대표 이미지") private String image; @@ -53,7 +53,7 @@ public class GetAllPlaceRes { private Double distance; @Builder - public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Float latitude, Float longitude, + public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Double latitude, Double longitude, String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, LocalDateTime createdAt, Integer recommendationScore, Double distance) { this.placeId = placeId; From 9c2601615174e0bea81a250d376d8cb793dfd382 Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 11 Feb 2024 20:03:47 +0900 Subject: [PATCH 223/356] =?UTF-8?q?[Feat]=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=EC=8B=9C=20=ED=9A=8C=EC=9B=90=EC=9D=98=20status=20INA?= =?UTF-8?q?CTIVE=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 43 +++++++++++++++---- .../domain/repository/MemberRepository.java | 5 ++- .../FailureMemberDeleteException.java | 9 ++++ .../member/presentation/MemberController.java | 23 +++++++++- 4 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/member/exception/FailureMemberDeleteException.java diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index bd042700..a372ddac 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -10,6 +10,7 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.DefaultAssert; @@ -18,12 +19,14 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.naming.spi.ResolveResult; import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; @RequiredArgsConstructor @@ -160,7 +163,6 @@ public void deleteValueByKey(String key) { } @Transactional - // 회원탈퇴 public ResponseEntity deleteUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); Optional checkMember = memberRepository.findById(memberId); @@ -170,15 +172,21 @@ public ResponseEntity deleteUser(HttpServletRequest request) { } Member member = checkMember.get(); - if (member.getStatus() == Status.INACTIVE) { - return ResponseEntity.badRequest().body(new InvalidMemberException("이미 탈퇴한 회원입니다.")); + if (member.getStatus() != Status.INACTIVE) { + member = Member.builder() + .id(member.getId()) + .oAuthId(member.getOAuthId()) + .nickname(member.getNickname()) + .memberNumber(member.getMemberNumber()) + .email(member.getEmail()) + .platformId(member.getPlatformId()) + .platform(member.getPlatform()) + .status(Status.INACTIVE) // 상태를 비활성화로 설정 + .refreshToken(member.getRefreshToken()) + .build(); + memberRepository.save(member); } - member = Member.builder().status(Status.INACTIVE).build(); - memberRepository.save(member); - - LocalDateTime deleteTime = LocalDateTime.now().plusDays(WAITING_PERIOD_DAYS); - ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()) @@ -186,4 +194,23 @@ public ResponseEntity deleteUser(HttpServletRequest request) { return ResponseEntity.ok(apiResponse); } + + + + @Transactional + public ResponseEntity deleteInactiveMember() { + try { + // 비활성화 된 회원 찾기 + List memberStatus = memberRepository.findByStatus(Status.INACTIVE); + + // 비활성회 된 회원 탈퇴 + for (Member member : memberStatus) { + memberRepository.delete(member); + } + + return ResponseEntity.ok("비활성화된 회원 탈퇴 완료"); + } catch (Exception e) { + throw new FailureMemberDeleteException(); + } + } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index ebb7d157..5e3d7477 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.member.domain.repository; import com.ttubeog.domain.auth.domain.Platform; +import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import io.lettuce.core.dynamic.annotation.Param; @@ -10,6 +11,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository @@ -21,8 +23,7 @@ public interface MemberRepository extends JpaRepository{ Optional findByEmail(String email); Optional findByMemberNumber(String memberNumber); - @Query("SELECT m.status FROM Member m WHERE m.id = :memberId") - Optional findMemberStatus(@Param("memberId") Long memberId); + List findByStatus(Status status); Optional findByPlatformAndPlatformId(Platform platform, String platformId); diff --git a/src/main/java/com/ttubeog/domain/member/exception/FailureMemberDeleteException.java b/src/main/java/com/ttubeog/domain/member/exception/FailureMemberDeleteException.java new file mode 100644 index 00000000..ac9a46f6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/exception/FailureMemberDeleteException.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.member.exception; + + +public class FailureMemberDeleteException extends RuntimeException { + + public FailureMemberDeleteException(){ + super("회원 탈퇴를 실패하였습니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 5220ae95..ce8ca9f2 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -17,12 +17,18 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.time.LocalDateTime; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + @Tag(name = "Member", description = "Member API") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/member") public class MemberController { private final MemberService memberService; + private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") @ApiResponses(value = { @@ -83,6 +89,21 @@ public ResponseEntity logout( public ResponseEntity deleteUser( HttpServletRequest request ) { - return memberService.deleteUser(request); + ResponseEntity responseEntity = memberService.deleteUser(request); + + if (responseEntity.getStatusCode().is2xxSuccessful()) { + LocalDateTime localDateTime = LocalDateTime.now().plusDays(3); + + scheduledExecutorService.schedule(() -> { + ResponseEntity deleteResponse = memberService.deleteInactiveMember(); + + if (deleteResponse.getStatusCode().is2xxSuccessful()) { + System.out.println("회원 삭제 성공"); + } else { + System.out.println("회원 삭제 실패"); + } + }, 3, TimeUnit.DAYS); + } + return responseEntity; } } From 3beb2dae937c14331253b6dddd716983d49ae682 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 12 Feb 2024 10:33:37 +0900 Subject: [PATCH 224/356] =?UTF-8?q?[Chore]=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=EC=97=90=20@Builder=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/dto/response/GetStoreDetailRes.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index 6f6ac466..a53b10c8 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -10,7 +10,6 @@ import java.util.List; @Data -@Builder @JsonInclude(JsonInclude.Include.NON_NULL) public class GetStoreDetailRes { @@ -55,4 +54,24 @@ public class GetStoreDetailRes { @Schema(description = "좋아요 수") private Integer likesCount; + + @Builder + public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, + String detailAddress, Double latitude, Double longitude, List image, Float stars, + StoreType type, List storeBenefits, Integer guestbookCount, Integer likesCount) { + this.storeId = storeId; + this.memberId = memberId; + this.name = name; + this.info = info; + this.dongAreaId = dongAreaId; + this.detailAddress = detailAddress; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.stars = stars; + this.type = type; + this.storeBenefits = storeBenefits; + this.guestbookCount = guestbookCount; + this.likesCount = likesCount; + } } From 323441b820da199fded5546b2f5d6c6dc8785cd6 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 12 Feb 2024 10:35:45 +0900 Subject: [PATCH 225/356] =?UTF-8?q?[Chore]=20import=EB=AC=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/store/domain/Store.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 4f9ec52c..930e0ddc 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -3,8 +3,13 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.member.domain.Member; +import jakarta.persistence.Table; import jakarta.persistence.*; -import lombok.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; @Entity @Getter From 616d611ef7d6382b51bafc0d1867b8ee8bf88fca Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 12 Feb 2024 21:22:46 +0900 Subject: [PATCH 226/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=97=AC=EB=B6=80=EB=A5=BC=20=EB=82=98?= =?UTF-8?q?=ED=83=80=EB=82=B4=EB=8A=94=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/member/domain/Member.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index c172a66b..2620d2b9 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -45,6 +45,9 @@ public class Member extends BaseEntity { @Column(name = "refresh_token") private String refreshToken; + @Column(name = "nickname_changed") + private boolean nicknameChange; + public Member(String email, Platform platform, Status status, String memberNumber) { this.email = email; From 61181eeeafa68f646bfbeaacdf3d7458bd602c03 Mon Sep 17 00:00:00 2001 From: arinming Date: Mon, 12 Feb 2024 21:42:56 +0900 Subject: [PATCH 227/356] =?UTF-8?q?[Feat]=20=ED=83=88=ED=87=B4=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EC=9C=BC=EB=A1=9C=2072=EC=8B=9C=EA=B0=84=20=EB=82=B4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=8B=9C=20ACTIVE=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84-=EC=9E=84=EC=8B=9C=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/AuthService.java | 21 +++++++++++++++---- .../ttubeog/domain/member/domain/Member.java | 5 +++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index be2483dc..4cdc2bec 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -58,6 +58,7 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { .memberNumber(String.valueOf(memberInfo.getId())) .platform(Platform.KAKAO) .status(Status.ACTIVE) + .nicknameChange(false) .build(); memberRepository.save(member); @@ -100,7 +101,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String return new OAuthTokenResponse(accessToken, refreshToken, true); }) .orElseGet(() -> { - Member newMember = new Member(email, platform, Status.ACTIVE, platformId); + Member newMember = new Member(email, platform, Status.ACTIVE, platformId, false); Member savedMember = memberRepository.save(newMember); String accessToken = issueAccessToken(savedMember); String refreshToken = issueRefreshToken(); @@ -118,9 +119,21 @@ private String issueRefreshToken() { return Token.createRefreshToken(); } - private void validateStatus(final Member findMember) { - if (findMember.getStatus() != Status.ACTIVE) { - throw new InvalidMemberException(); + private void validateStatus(final Member member) { + + // 멤버가 탈퇴해서 INACTIVE 된 경우 + if (member.getStatus() != Status.ACTIVE) { + Member.builder() + .id(member.getId()) + .oAuthId(member.getOAuthId()) + .nickname(member.getNickname()) + .memberNumber(member.getMemberNumber()) + .email(member.getEmail()) + .platformId(member.getPlatformId()) + .platform(member.getPlatform()) + .status(Status.ACTIVE) // 상태를 비활성화로 설정 + .refreshToken(member.getRefreshToken()) + .build(); } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 2620d2b9..ea30dc85 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -46,15 +46,16 @@ public class Member extends BaseEntity { private String refreshToken; @Column(name = "nickname_changed") - private boolean nicknameChange; + private Boolean nicknameChange; - public Member(String email, Platform platform, Status status, String memberNumber) { + public Member(String email, Platform platform, Status status, String memberNumber, Boolean nicknameChange) { this.email = email; this.platform = platform; this.platformId = platformId; this.status = status; this.memberNumber = memberNumber; + this.nicknameChange = nicknameChange; } public Member(Status status) { From 42122bdfdf0ffec544862117b5c73445c19493aa Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 01:06:24 +0900 Subject: [PATCH 228/356] =?UTF-8?q?[Chore]=20Comment=20=ED=98=84=EC=9E=AC?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=20=ED=99=95=EC=9D=B8=20=EB=B0=A9=EB=B2=95?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 18 ++++++++++++------ .../presentation/CommentController.java | 13 +++++++------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 1773b996..6b173662 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.comment.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.comment.domain.Comment; import com.ttubeog.domain.comment.domain.repository.CommentRepository; import com.ttubeog.domain.comment.dto.request.GetCommentReq; @@ -17,6 +18,7 @@ import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -34,12 +36,14 @@ public class CommentService { private final CommentRepository commentRepository; private final MemberRepository memberRepository; + private final JwtTokenProvider jwtTokenProvider; // 댓글 작성 @Transactional - public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentReq writeCommentReq) { + public ResponseEntity writeComment(HttpServletRequest request, WriteCommentReq writeCommentReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = Comment.builder() .content(writeCommentReq.getContent()) @@ -68,9 +72,10 @@ public ResponseEntity writeComment(UserPrincipal userPrincipal, WriteCommentR // 댓글 수정 @Transactional - public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommentReq updateCommentReq) { + public ResponseEntity updateComment(HttpServletRequest request, UpdateCommentReq updateCommentReq) { - Member member = memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = commentRepository.findById(updateCommentReq.getCommentId()).orElseThrow(NonExistentCommentException::new); Member commentWriter = comment.getMember(); @@ -95,9 +100,10 @@ public ResponseEntity updateComment(UserPrincipal userPrincipal, UpdateCommen // 댓글 삭제 @Transactional - public ResponseEntity deleteComment(UserPrincipal userPrincipal, Long commentId) { + public ResponseEntity deleteComment(HttpServletRequest request, Long commentId) { - memberRepository.findById(userPrincipal.getId()).orElseThrow(InvalidMemberException::new); + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = commentRepository.findById(commentId).orElseThrow(NonExistentCommentException::new); commentRepository.delete(comment); diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index f214e68a..ac7adb7f 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -40,10 +41,10 @@ public class CommentController { }) @PostMapping public ResponseEntity writeComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody WriteCommentReq writeCommentReq ) { - return commentService.writeComment(userPrincipal, writeCommentReq); + return commentService.writeComment(request, writeCommentReq); } // 댓글 수정 @@ -54,10 +55,10 @@ public ResponseEntity writeComment( }) @PatchMapping public ResponseEntity updateComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @Valid @RequestBody UpdateCommentReq updateCommentReq ) { - return commentService.updateComment(userPrincipal, updateCommentReq); + return commentService.updateComment(request, updateCommentReq); } // 댓글 삭제 @@ -68,10 +69,10 @@ public ResponseEntity updateComment( }) @DeleteMapping("/{commentId}") public ResponseEntity deleteComment( - @Parameter(description = "AccessToken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, + HttpServletRequest request, @PathVariable Long commentId ) { - return commentService.deleteComment(userPrincipal, commentId); + return commentService.deleteComment(request, commentId); } // AR뷰 댓글 조회 (반경 이용) From 27f5457cc9bfa4542d593039560cd510f8a5cf50 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 04:26:50 +0900 Subject: [PATCH 229/356] =?UTF-8?q?[Fix]=20=EB=8C=93=EA=B8=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20Query=20Parameters=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/presentation/CommentController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index ac7adb7f..351b769c 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.comment.dto.request.GetCommentReq; import com.ttubeog.domain.comment.dto.request.UpdateCommentReq; import com.ttubeog.domain.comment.dto.request.WriteCommentReq; +import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; import com.ttubeog.global.config.security.token.CurrentUser; @@ -78,12 +79,12 @@ public ResponseEntity deleteComment( // AR뷰 댓글 조회 (반경 이용) @Operation(summary = "댓글 조회", description = "반경 내의 댓글을 조회힙니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = List.class))}), + @ApiResponse(responseCode = "200", description = "댓글 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetCommentRes.class))}), @ApiResponse(responseCode = "400", description = "댓글 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping public ResponseEntity getCommentForAR( - @Valid @RequestBody GetCommentReq getCommentReq + @Valid GetCommentReq getCommentReq ) { return commentService.getCommentForAR(getCommentReq); } From 84629a0b849e9bfd36bb4a1e6e573202193cebd7 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 9 Feb 2024 04:36:07 +0900 Subject: [PATCH 230/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/comment/application/CommentService.java | 4 ---- .../domain/comment/presentation/CommentController.java | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 6b173662..276b17d4 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -14,8 +14,6 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; @@ -26,8 +24,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; - @RequiredArgsConstructor @Service diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index 351b769c..b6b6e7e3 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -7,12 +7,9 @@ import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -24,8 +21,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - @Tag(name = "Comment", description = "Comment API") @RestController @RequiredArgsConstructor From 7e91f2a1fe8c8e035d34db57b3fcb559a86a5e5e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 03:00:46 +0900 Subject: [PATCH 231/356] =?UTF-8?q?[Chore]=20Place=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=ED=99=95=EC=9D=B8=20=EB=B0=A9=EB=B2=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 45 ++++++++++++------- .../place/presentation/PlaceController.java | 28 +++++++----- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index e888c963..7ab7da36 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.place.application; import com.ttubeog.domain.auth.config.SecurityUtil; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -12,6 +15,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.payload.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -34,6 +38,9 @@ public class PlaceService { private final StoreRepository storeRepository; private final SpotRepository spotRepository; private final LikesRepository likesRepository; + private final ImageRepository imageRepository; + private final ImageService imageService; + private final JwtTokenProvider jwtTokenProvider; public List getPageOfPlaces(List places, int page, int size) { int startIndex = page * size; @@ -42,12 +49,12 @@ public List getPageOfPlaces(List places, int pag return places.subList(startIndex, endIndex); } - public List getAllPlaceResList(Pageable pageable) { + public List getAllPlaceResList(HttpServletRequest request, Pageable pageable) { List places = new ArrayList<>(); List stores = storeRepository.findAll(); - places.addAll(stores.stream().map(this::mapStoreToDto).collect(Collectors.toList())); + places.addAll(stores.stream().map(store -> mapStoreToDto(request, store)).collect(Collectors.toList())); // List spots = spotRepository.findAll(); // places.addAll(spots.stream().map(this::mapSpotToDto).collect(Collectors.toList())); int page = pageable.getPageNumber(); @@ -56,10 +63,12 @@ public List getAllPlaceResList(Pageable pageable) { return getPageOfPlaces(places, page, size); } - private GetAllPlaceRes mapStoreToDto(Store store) { + private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { - final long memberId = SecurityUtil.getCurrentMemeberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + // 현재 로그인 유저의 좋아요 여부 Boolean storeLiked = likesRepository.existsByMemberIdAndStoreId(memberId, store.getId()); PlaceType placeType = new PlaceType(true, false); @@ -70,7 +79,7 @@ private GetAllPlaceRes mapStoreToDto(Store store) { .name(store.getName()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - //.image(store.getImage()) + // .image(store.getImage()) .stars(store.getStars()) // .guestbookCount(guestRepository.countByStoreId(store.getID())) .isFavorited(storeLiked) @@ -82,6 +91,8 @@ private GetAllPlaceRes mapStoreToDto(Store store) { final long memberId = SecurityUtil.getCurrentMemberId(); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + // 현재 로그인 유저의 좋아요 여부 Boolean spotLiked = likesRepository.existsByMemberIdAndSpotId(memberId, spot.getId()); PlaceType placeType = new PlaceType(false, true); @@ -102,12 +113,12 @@ private GetAllPlaceRes mapStoreToDto(Store store) { // 전체 조회 @Transactional - public ResponseEntity getAllPlaces(Pageable pageable) { + public ResponseEntity getAllPlaces(HttpServletRequest request, Pageable pageable) { - final long memberId = SecurityUtil.getCurrentMemeberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(pageable); + List allPlaces = getAllPlaceResList(request, pageable); ApiResponse apiResponse = ApiResponse.builder() .check(true) @@ -151,11 +162,11 @@ private int calculateLikesStore(int likesCount) { // 추천순 조회 @Transactional - public ResponseEntity getAllPlacesRecommended(Pageable pageable) { + public ResponseEntity getAllPlacesRecommended(HttpServletRequest request, Pageable pageable) { - final long memberId = SecurityUtil.getCurrentMemeberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(pageable); + List allPlaces = getAllPlaceResList(request, pageable); for (GetAllPlaceRes place : allPlaces) { int recommendationScore = calculateRecommendationScore(place.getStars(), place.getGuestbookCount(), place.getLikesCount()); @@ -190,11 +201,11 @@ private double calculateDistance(Double lat1, Double lon1, Double lat2, Double l // 거리순 조회 @Transactional - public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq, Pageable pageable) { + public ResponseEntity getAllPlacesNearby(HttpServletRequest request, GetNearbyPlaceReq getNearbyPlaceReq, Pageable pageable) { - final long memberId = SecurityUtil.getCurrentMemeberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(pageable); + List allPlaces = getAllPlaceResList(request, pageable); Double userLatitude = getNearbyPlaceReq.getLatitude(); Double userLongitude = getNearbyPlaceReq.getLongitude(); @@ -216,11 +227,11 @@ public ResponseEntity getAllPlacesNearby(GetNearbyPlaceReq getNearbyPlaceReq, // 최신순 조회 @Transactional - public ResponseEntity getAllPlacesLatest(Pageable pageable) { + public ResponseEntity getAllPlacesLatest(HttpServletRequest request, Pageable pageable) { - final long memberId = SecurityUtil.getCurrentMemeberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List allPlaces = getAllPlaceResList(pageable); + List allPlaces = getAllPlaceResList(request, pageable); allPlaces.sort(Comparator.comparing(GetAllPlaceRes::getCreatedAt).reversed()); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 57b525b7..8990c0ca 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; @@ -32,10 +33,12 @@ public class PlaceController { @ApiResponse(responseCode = "400", description = "전체 장소 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping - public ResponseEntity getAllPlaces(@RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + public ResponseEntity getAllPlaces( + HttpServletRequest request, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlaces(pageable); + return placeService.getAllPlaces(request, pageable); } // 추천순 조회 @@ -45,10 +48,12 @@ public ResponseEntity getAllPlaces(@RequestParam(defaultValue = "0") int page @ApiResponse(responseCode = "400", description = "추천순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/recommended") - public ResponseEntity getAllPlacesRecommended(@RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + public ResponseEntity getAllPlacesRecommended( + HttpServletRequest request, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesRecommended(pageable); + return placeService.getAllPlacesRecommended(request, pageable); } // 거리순 조회 @@ -59,12 +64,13 @@ public ResponseEntity getAllPlacesRecommended(@RequestParam(defaultValue = "0 }) @GetMapping("/nearby") public ResponseEntity getAllPlacesNearby( + HttpServletRequest request, @Valid @RequestBody GetNearbyPlaceReq getNearbyPlaceReq, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesNearby(getNearbyPlaceReq, pageable); + return placeService.getAllPlacesNearby(request, getNearbyPlaceReq, pageable); } // 최신순 조회 @@ -74,9 +80,11 @@ public ResponseEntity getAllPlacesNearby( @ApiResponse(responseCode = "400", description = "최신순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/latest") - public ResponseEntity getAllPlacesLatest(@RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + public ResponseEntity getAllPlacesLatest( + HttpServletRequest request, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesLatest(pageable); + return placeService.getAllPlacesLatest(request, pageable); } } From bfb39528f3399a693a502ed2510273f31e96775b Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 13 Feb 2024 13:24:28 +0900 Subject: [PATCH 232/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/application/MemberService.java | 16 ++++++++++++---- .../com/ttubeog/domain/member/domain/Member.java | 1 + .../domain/repository/MemberRepository.java | 3 +-- .../member/dto/response/MemberDetailRes.java | 2 ++ .../AlreadyChangeNicknameException.java | 9 +++++++++ 5 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/member/exception/AlreadyChangeNicknameException.java diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index a372ddac..e2986a62 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -10,6 +10,7 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.member.exception.AlreadyChangeNicknameException; import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -19,13 +20,10 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.naming.spi.ResolveResult; -import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -86,7 +84,17 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } - memberRepository.updateUserNickname(produceNicknameRequest.getNickname(), memberId); + // 닉네임 1회 변경 여부 확인 + Optional checkMemberIsChanged = memberRepository.findById(memberId); + if (checkMemberIsChanged.isPresent()) { + Member member = checkMemberIsChanged.get(); + if (member.isNickNameChanged()) { + throw new AlreadyChangeNicknameException(); + } + } + + // 닉네임 업데이트 + memberRepository.updateMemberNickname(produceNicknameRequest.getNickname(), memberId); Optional checkMember = memberRepository.findById(memberId); diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index ea30dc85..953d1c3b 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -64,6 +64,7 @@ public Member(Status status) { public boolean isRegisteredOAuthMember() { return nickname != null; } + public boolean isNickNameChanged() { return nicknameChange; } public void updateName(String name) { this.nickname = name; diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 5e3d7477..54305d85 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -3,7 +3,6 @@ import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import io.lettuce.core.dynamic.annotation.Param; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; @@ -36,7 +35,7 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") - void updateUserNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); + void updateMemberNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); Boolean existsByNickname(String nickname); diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index 726d3f82..77587b70 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -21,6 +21,8 @@ public class MemberDetailRes { private Boolean isUsed; + private Boolean isChanged; + public static MemberDetailRes toDto(Member member) { return MemberDetailRes.builder() .id(member.getId()) diff --git a/src/main/java/com/ttubeog/domain/member/exception/AlreadyChangeNicknameException.java b/src/main/java/com/ttubeog/domain/member/exception/AlreadyChangeNicknameException.java new file mode 100644 index 00000000..b2a72964 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/exception/AlreadyChangeNicknameException.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.member.exception; + + +public class AlreadyChangeNicknameException extends RuntimeException { + + public AlreadyChangeNicknameException(){ + super("이미 닉네임을 변경한 회원입니다."); + } +} From 6826308948b214e32e247aedb5895cd89c0fc33f Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 13 Feb 2024 14:17:45 +0900 Subject: [PATCH 233/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=ED=99=95=EC=9D=B8=EA=B3=BC=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EC=84=A4=EC=A0=95=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 33 ++++++++----------- .../member/presentation/MemberController.java | 12 +++++++ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index e2986a62..db11b163 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -65,25 +65,6 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); - if (memberRepository.existsByNickname(produceNicknameRequest.getNickname())) { - Optional checkMember = memberRepository.findById(memberId); - Member member = checkMember.get(); - - MemberDetailRes memberDetailRes = MemberDetailRes.builder() - .id(member.getId()) - .name(member.getNickname()) - .platform(member.getPlatform()) - .isUsed(false) - .build(); - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(memberDetailRes) - .build(); - - return ResponseEntity.ok(apiResponse); - } - // 닉네임 1회 변경 여부 확인 Optional checkMemberIsChanged = memberRepository.findById(memberId); if (checkMemberIsChanged.isPresent()) { @@ -115,6 +96,20 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN return ResponseEntity.ok(apiResponse); } + @Transactional + // 닉네임 중복 확인 + public ResponseEntity postMemberNicknameCheck(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { + Long memberId = jwtTokenProvider.getMemberId(request); + + Boolean isNicknameUsed = memberRepository.existsByNickname(produceNicknameRequest.getNickname()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(!isNicknameUsed) + .information("닉네임 중복이면 check -> false, 중복이 아니면 check -> true") + .build(); + return ResponseEntity.ok(apiResponse); + } + @Transactional // 토큰 재발급 설정 public ResponseEntity getMemberReissueToken(HttpServletRequest request) { diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index ce8ca9f2..b36d491f 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -55,6 +55,18 @@ public ResponseEntity postMemberNickname( return memberService.postMemberNickname(request, produceNicknameRequest); } + @Operation(summary = "닉네임 중복 확인", description = "닉네임의 중복을 확인합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "닉네임 설정 가능", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @PostMapping(value = "/nickname/check") + public ResponseEntity checkNicknameAvailability( + HttpServletRequest request, @RequestBody ProduceNicknameRequest produceNicknameRequest + ) { + return memberService.postMemberNicknameCheck(request, produceNicknameRequest); + } + @Operation(summary = "토큰 재발급", description = "현재 접속된 멤버의 토큰을 재발급 합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "토큰 재발급 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = OAuthTokenResponse.class))}), From 0d31f41f8c88829786ff8e60f217a00791234e3f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 16:18:06 +0900 Subject: [PATCH 234/356] =?UTF-8?q?[Chore]=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 96b646c4..dce3095b 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -78,7 +78,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore for (String s : imageList) { CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(s) - .imageType(ImageType.SPOT) + .imageType(ImageType.STORE) .placeId(store.getId()) .build(); imageService.createImage(createImageRequestDto); @@ -114,6 +114,7 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(updateStoreReq.getStoreId()).orElseThrow(NonExistentStoreException::new); + // 현재 유저가 매장 등록 유저인지 확인 Long storeOwnerId = store.getMember().getId(); if (!storeOwnerId.equals(memberId)) { throw new UnathorizedMemberException(); @@ -143,7 +144,7 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq for (String s : imageStringList) { CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(s) - .imageType(ImageType.SPOT) + .imageType(ImageType.STORE) .placeId(store.getId()) .build(); imageService.createImage(createImageRequestDto); @@ -177,6 +178,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); + // 현재 유저가 매장 등록 유저인지 확인 Long storeOwnerId = store.getMember().getId(); if (!storeOwnerId.equals(memberId)) { throw new UnathorizedMemberException(); From 8b4291871e5f1aa022b555f186e4812fc2add62e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 16:29:26 +0900 Subject: [PATCH 235/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20=EA=B4=80=EB=A0=A8=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/BenefitRepository.java | 2 ++ .../repository/GuestBookRepository.java | 3 ++ .../domain/repository/LikesRepository.java | 3 ++ .../store/application/StoreService.java | 30 +++++++++++++++---- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java index 25235760..a87eebe2 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java @@ -14,4 +14,6 @@ public interface BenefitRepository extends JpaRepository { Optional findByGame(Game game); List findAllByGame(Game game); + + List findByStoreId(Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 73ec6480..4cb7e951 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface GuestBookRepository extends JpaRepository { + List findByStoreId(Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index b0794425..08fb4e17 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface LikesRepository extends JpaRepository { + List findByStoreId(Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index dce3095b..b5d8ba5a 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -3,11 +3,17 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.guestbook.domain.GuestBook; +import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; +import com.ttubeog.domain.likes.domain.Likes; +import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; @@ -43,6 +49,9 @@ public class StoreService { private final MemberRepository memberRepository; private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; + private final BenefitRepository benefitRepository; + private final GuestBookRepository guestBookRepository; + private final LikesRepository likesRepository; private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; @@ -184,12 +193,23 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { throw new UnathorizedMemberException(); } - storeRepository.delete(store); + // 해당 매장과 연관된 혜택 삭제 + List benefits = benefitRepository.findByStoreId(storeId); + benefitRepository.deleteAll(benefits); - List imageList = imageRepository.findByStoreId(store.getId()); - for (Image image : imageList) { - imageService.deleteImage(image.getId()); - } + // 해당 매장과 연관된 방명록 삭제 + List guestBooks = guestBookRepository.findByStoreId(storeId); + guestBookRepository.deleteAll(guestBooks); + + // 해당 매장과 연관된 좋아요 삭제 + List likes = likesRepository.findByStoreId(storeId); + likesRepository.deleteAll(likes); + + // 해당 매장과 연관된 이미지 삭제 + List images = imageRepository.findByStoreId(storeId); + imageRepository.deleteAll(images); + + storeRepository.delete(store); ApiResponse apiResponse = ApiResponse.builder() .check(true) From ec2ff4e99b048056cf1171fd53ccc07d809e0b71 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 18:12:25 +0900 Subject: [PATCH 236/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=84=B8?= =?UTF-8?q?=EB=B6=80=EC=82=AC=ED=95=AD=20=EC=A1=B0=ED=9A=8C=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/domain/GuestBook.java | 10 ++++++---- .../repository/GuestBookRepository.java | 2 ++ .../ttubeog/domain/likes/domain/Likes.java | 10 ++++++---- .../domain/repository/LikesRepository.java | 4 ++++ .../store/application/StoreService.java | 19 +++++++++++++------ .../store/dto/response/GetStoreDetailRes.java | 6 +++++- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java index b42c4d0c..715b24f1 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java @@ -1,10 +1,8 @@ package com.ttubeog.domain.guestbook.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; import lombok.Getter; @Getter @@ -14,4 +12,8 @@ public class GuestBook extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 4cb7e951..92b1d9fa 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -9,4 +9,6 @@ @Repository public interface GuestBookRepository extends JpaRepository { List findByStoreId(Long storeId); + + Integer countByStoreId(Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java index bb7b91a1..0eda9a93 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java @@ -1,10 +1,8 @@ package com.ttubeog.domain.likes.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; @Entity public class Likes extends BaseEntity { @@ -12,4 +10,8 @@ public class Likes extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index 08fb4e17..6ec3f37e 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -9,4 +9,8 @@ @Repository public interface LikesRepository extends JpaRepository { List findByStoreId(Long storeId); + + Integer countByStoreId(Long storeId); + + Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index b5d8ba5a..28fd1979 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.BenefitType; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; @@ -37,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.stream.Collectors; import static com.ttubeog.domain.image.application.ImageService.getImageString; @@ -226,9 +228,13 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); - // List storeBenefits = benefitRepository.findTypeByStoreId(storeId); - // Integer guestbookCount = guestBookRepository.countByStoreId(storeId); - // Integer likesCount = likesRepository.countByStoreId(storeId); + List storeBenefits = benefitRepository.findByStoreId(storeId) + .stream() + .map(Benefit::getType) + .collect(Collectors.toList()); + Integer guestbookCount = guestBookRepository.countByStoreId(storeId); + Integer likesCount = likesRepository.countByStoreId(storeId); + Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() .storeId(storeId) @@ -242,9 +248,10 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) - //.storeBenefits(storeBenefits.stream().map(BenefitType::getType).collect(Collectors.toList())) - //.guestbookCount(guestbookCount) - //.likesCount(likesCount) + .storeBenefits(storeBenefits) + .guestbookCount(guestbookCount) + .likesCount(likesCount) + .isFavorited(isFavorited) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index a53b10c8..834a4384 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -55,10 +55,13 @@ public class GetStoreDetailRes { @Schema(description = "좋아요 수") private Integer likesCount; + @Schema(description = "현재 유저의 좋아요 여부") + private Boolean isFavorited; + @Builder public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, String detailAddress, Double latitude, Double longitude, List image, Float stars, - StoreType type, List storeBenefits, Integer guestbookCount, Integer likesCount) { + StoreType type, List storeBenefits, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { this.storeId = storeId; this.memberId = memberId; this.name = name; @@ -73,5 +76,6 @@ public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, this.storeBenefits = storeBenefits; this.guestbookCount = guestbookCount; this.likesCount = likesCount; + this.isFavorited = isFavorited; } } From 412f0cffedde17eaed4ec0817b980d9c90c48297 Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 13 Feb 2024 18:22:56 +0900 Subject: [PATCH 237/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?1=ED=9A=8C=20=EB=B3=80=EA=B2=BD=EC=8B=9C=20nicknameChange=20?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/member/application/MemberService.java | 6 ++++-- .../domain/member/domain/repository/MemberRepository.java | 5 +++++ .../ttubeog/domain/member/dto/response/MemberDetailRes.java | 2 -- .../domain/member/presentation/MemberController.java | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index db11b163..936fe73f 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -77,15 +77,17 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN // 닉네임 업데이트 memberRepository.updateMemberNickname(produceNicknameRequest.getNickname(), memberId); - Optional checkMember = memberRepository.findById(memberId); + // 닉네임 1회 변경 true로 변경 + memberRepository.updateMemberNicknameChange(true, memberId); + Optional checkMember = memberRepository.findById(memberId); Member member = checkMember.get(); MemberDetailRes memberDetailRes = MemberDetailRes.builder() .id(member.getId()) .name(member.getNickname()) .platform(member.getPlatform()) - .isUsed(true) + .isChanged(member.getNicknameChange()) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 54305d85..9992126d 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -37,6 +37,11 @@ public interface MemberRepository extends JpaRepository{ @Query("update Member as m set m.nickname = :nickName where m.id = :memberId") void updateMemberNickname(@Param("nickName") String nickName, @Param("memberId") Long memberId); + @Modifying + @Query("update Member as m set m.nicknameChange = :nicknameChange where m.id = :memberId") + void updateMemberNicknameChange(@Param("nicknameChange") Boolean nicknameChange, @Param("memberId") Long memberId); + + Boolean existsByNickname(String nickname); } diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java index 77587b70..3011e08f 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java @@ -19,8 +19,6 @@ public class MemberDetailRes { private Platform platform; - private Boolean isUsed; - private Boolean isChanged; public static MemberDetailRes toDto(Member member) { diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index b36d491f..f00ffd22 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -57,7 +57,7 @@ public ResponseEntity postMemberNickname( @Operation(summary = "닉네임 중복 확인", description = "닉네임의 중복을 확인합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "닉네임 설정 가능", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "200", description = "닉네임 설정 가능", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = com.ttubeog.global.payload.ApiResponse.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname/check") @@ -67,6 +67,7 @@ public ResponseEntity checkNicknameAvailability( return memberService.postMemberNicknameCheck(request, produceNicknameRequest); } + @Operation(summary = "토큰 재발급", description = "현재 접속된 멤버의 토큰을 재발급 합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "토큰 재발급 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = OAuthTokenResponse.class))}), From 82d77cf8f8e92023bdbb1661ab6da1d0eda2e9bc Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 18:43:40 +0900 Subject: [PATCH 238/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20=EA=B4=80=EB=A0=A8=EB=90=9C=20MemberBen?= =?UTF-8?q?efit=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MemberBenefitRepository.java | 2 ++ .../domain/store/application/StoreService.java | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index c9987675..8859fba3 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -24,4 +24,6 @@ public interface MemberBenefitRepository extends JpaRepository findAllByMember(Member member, PageRequest pageRequest); List findAllByMemberAndBenefitIn(Member member, List benefits); + + List findByBenefitId(Long id); } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 28fd1979..29f22209 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -5,7 +5,9 @@ import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.BenefitType; +import com.ttubeog.domain.benefit.domain.MemberBenefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; @@ -52,6 +54,7 @@ public class StoreService { private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; private final BenefitRepository benefitRepository; + private final MemberBenefitRepository memberBenefitRepository; private final GuestBookRepository guestBookRepository; private final LikesRepository likesRepository; private final ImageService imageService; @@ -195,6 +198,13 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { throw new UnathorizedMemberException(); } + // 특정 유저가 가진 해당 매장의 혜택 삭제 + List benefitsToDelete = benefitRepository.findByStoreId(storeId); + for (Benefit benefit : benefitsToDelete) { + List memberBenefits = memberBenefitRepository.findByBenefitId(benefit.getId()); + memberBenefitRepository.deleteAll(memberBenefits); + } + // 해당 매장과 연관된 혜택 삭제 List benefits = benefitRepository.findByStoreId(storeId); benefitRepository.deleteAll(benefits); @@ -211,6 +221,9 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { List images = imageRepository.findByStoreId(storeId); imageRepository.deleteAll(images); + // TODO 해당 매장과 연관된 경로 삭제 + // TODO 해당 매장과 연관된 저장경로 삭제 + storeRepository.delete(store); ApiResponse apiResponse = ApiResponse.builder() From 4d3e9f091d031b6a847da9ecddf65933c0cad97b Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 13 Feb 2024 19:14:51 +0900 Subject: [PATCH 239/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=EC=9D=84=201=ED=9A=8C=20=EB=B3=80=EA=B2=BD=ED=95=9C=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=EB=8A=94=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B6=88=EA=B0=80=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B5=AC=ED=98=84=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 23 +++++++++++---- .../dto/response/MemberNicknameRes.java | 29 +++++++++++++++++++ .../member/presentation/MemberController.java | 5 ++-- 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 936fe73f..26c6b8bc 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -10,6 +10,7 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.member.dto.response.MemberNicknameRes; import com.ttubeog.domain.member.exception.AlreadyChangeNicknameException; import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; @@ -70,7 +71,20 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN if (checkMemberIsChanged.isPresent()) { Member member = checkMemberIsChanged.get(); if (member.isNickNameChanged()) { - throw new AlreadyChangeNicknameException(); + Member checkMember = memberRepository.findById(memberId).get(); + + MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() + .id(checkMember.getId()) + .nickname(checkMember.getNickname()) + .isChanged(checkMember.getNicknameChange()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(false) + .information(memberNicknameRes) + .build(); + + return ResponseEntity.ok(apiResponse); } } @@ -83,16 +97,15 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN Optional checkMember = memberRepository.findById(memberId); Member member = checkMember.get(); - MemberDetailRes memberDetailRes = MemberDetailRes.builder() + MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() .id(member.getId()) - .name(member.getNickname()) - .platform(member.getPlatform()) + .nickname(produceNicknameRequest.getNickname()) .isChanged(member.getNicknameChange()) .build(); ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(memberDetailRes) + .information(memberNicknameRes) .build(); return ResponseEntity.ok(apiResponse); diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java new file mode 100644 index 00000000..60823b39 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java @@ -0,0 +1,29 @@ +package com.ttubeog.domain.member.dto.response; + +import com.ttubeog.domain.auth.domain.Platform; +import com.ttubeog.domain.member.domain.Member; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@RequiredArgsConstructor +@AllArgsConstructor +@Builder +public class MemberNicknameRes { + + private Long id; + private String nickname; + + private Boolean isChanged; + + public static MemberNicknameRes toDto(Member member) { + return MemberNicknameRes.builder() + .id(member.getId()) + .nickname(member.getNickname()) + .isChanged(member.getNicknameChange()) + .build(); + } + +} diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index f00ffd22..2fbff1c2 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; +import com.ttubeog.domain.member.dto.response.MemberNicknameRes; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -43,9 +44,9 @@ public ResponseEntity getCurrentMember( return memberService.getCurrentUser(request); } - @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.") + @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.닉네임을 이미 변경한 유저는 isChanged == true로 반환되며, 닉네임이 업데이트 되지 않습니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberNicknameRes.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname") From 2cdc335bd88ce3513885d1407563a20f778d4e5a Mon Sep 17 00:00:00 2001 From: arinming Date: Tue, 13 Feb 2024 19:23:44 +0900 Subject: [PATCH 240/356] =?UTF-8?q?[Chore]=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=EC=9E=84=EC=8B=9C=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index ce8ca9f2..f4839850 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -80,30 +80,30 @@ public ResponseEntity logout( return memberService.deleteLogout(request); } - @Operation(summary = "회원탈퇴", description = "현재 접속된 회원이 탈퇴 합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "회원탈퇴 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), - @ApiResponse(responseCode = "400", description = "회원탈퇴 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), - }) - @DeleteMapping("/delete") - public ResponseEntity deleteUser( - HttpServletRequest request - ) { - ResponseEntity responseEntity = memberService.deleteUser(request); - - if (responseEntity.getStatusCode().is2xxSuccessful()) { - LocalDateTime localDateTime = LocalDateTime.now().plusDays(3); - - scheduledExecutorService.schedule(() -> { - ResponseEntity deleteResponse = memberService.deleteInactiveMember(); - - if (deleteResponse.getStatusCode().is2xxSuccessful()) { - System.out.println("회원 삭제 성공"); - } else { - System.out.println("회원 삭제 실패"); - } - }, 3, TimeUnit.DAYS); - } - return responseEntity; - } +// @Operation(summary = "회원탈퇴", description = "현재 접속된 회원이 탈퇴 합니다.") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "회원탈퇴 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), +// @ApiResponse(responseCode = "400", description = "회원탈퇴 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), +// }) +// @DeleteMapping("/delete") +// public ResponseEntity deleteUser( +// HttpServletRequest request +// ) { +// ResponseEntity responseEntity = memberService.deleteUser(request); +// +// if (responseEntity.getStatusCode().is2xxSuccessful()) { +// LocalDateTime localDateTime = LocalDateTime.now().plusDays(3); +// +// scheduledExecutorService.schedule(() -> { +// ResponseEntity deleteResponse = memberService.deleteInactiveMember(); +// +// if (deleteResponse.getStatusCode().is2xxSuccessful()) { +// System.out.println("회원 삭제 성공"); +// } else { +// System.out.println("회원 삭제 실패"); +// } +// }, 3, TimeUnit.DAYS); +// } +// return responseEntity; +// } } From 8ac5b4bf9435896974769bf33a80fe1a688f075b Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 1 Feb 2024 23:42:18 +0900 Subject: [PATCH 241/356] =?UTF-8?q?[Refac]=20Likes=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../likes/application/LikesService.java | 4 ++-- .../ttubeog/domain/likes/domain/Likes.java | 23 +++++++++++++++++-- .../domain/repository/LikesRepository.java | 3 ++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 4c61bc00..43a97070 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -54,7 +54,7 @@ public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(Message.builder().message("매장에 대한 좋아요를 눌렀습니다.")) + .information(Message.builder().message("매장에 대한 좋아요를 눌렀습니다.").build()) .build(); return ResponseEntity.ok(apiResponse); @@ -81,7 +81,7 @@ public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.")) + .information(Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.").build()) .build(); return ResponseEntity.ok(apiResponse); diff --git a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java index 0eda9a93..95a5eaac 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/Likes.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/Likes.java @@ -1,17 +1,36 @@ package com.ttubeog.domain.likes.domain; import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "likes") public class Likes extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne + @JoinColumn(name = "member_id") + private Member member; + + @ManyToOne @JoinColumn(name = "store_id") private Store store; -} + + @ManyToOne + @JoinColumn(name = "spot_id") + private Spot spot; +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index 6ec3f37e..92b1dcab 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -12,5 +12,6 @@ public interface LikesRepository extends JpaRepository { Integer countByStoreId(Long storeId); - Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); + boolean existsByMemberIdAndStoreId(Long memberId, Long StoreId); + boolean existsByMemberIdAndSpotId(Long memberId, Long spotId); } From e64db8fd249e05a79948165cbd7da6d8d633c76d Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Tue, 13 Feb 2024 20:16:49 +0900 Subject: [PATCH 242/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EB=88=84=EB=A5=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/store/presentation/StoreController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 31faf4b2..58589c53 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -88,7 +88,7 @@ public ResponseEntity getStoreDetails( } // 매장 좋아요 누르기 - /*Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") + @Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "매장 좋아요 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @ApiResponse(responseCode = "400", description = "매장 좋아요 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) @@ -99,5 +99,5 @@ public ResponseEntity likesStore( @PathVariable Long storeId ) { return likesService.likesStore(request, storeId); - }*/ + } } From d40291336d05ae4ab111b1888b0c1309b434b1b8 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Tue, 13 Feb 2024 20:37:12 +0900 Subject: [PATCH 243/356] =?UTF-8?q?Chore:=20Likes=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 29f22209..928599e3 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -247,7 +247,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .collect(Collectors.toList()); Integer guestbookCount = guestBookRepository.countByStoreId(storeId); Integer likesCount = likesRepository.countByStoreId(storeId); - Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); + //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() .storeId(storeId) @@ -264,7 +264,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .storeBenefits(storeBenefits) .guestbookCount(guestbookCount) .likesCount(likesCount) - .isFavorited(isFavorited) + //.isFavorited(isFavorited) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -274,4 +274,4 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI return ResponseEntity.ok(apiResponse); } -} \ No newline at end of file +} From d9f9facc46bb1b22dbf77b6bd3a2850898736e1b Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Tue, 13 Feb 2024 20:37:50 +0900 Subject: [PATCH 244/356] =?UTF-8?q?Chore:=20Likes=20=EB=A9=A4=EB=B2=84?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/likes/domain/repository/LikesRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index 6ec3f37e..15a0006e 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -12,5 +12,5 @@ public interface LikesRepository extends JpaRepository { Integer countByStoreId(Long storeId); - Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); + //Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); } From edfa154d397173f307e79ba3df72708b4aab9a30 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Tue, 13 Feb 2024 20:48:56 +0900 Subject: [PATCH 245/356] =?UTF-8?q?Chore:=20Likes=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 928599e3..02791884 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -247,7 +247,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .collect(Collectors.toList()); Integer guestbookCount = guestBookRepository.countByStoreId(storeId); Integer likesCount = likesRepository.countByStoreId(storeId); - //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); + // Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() .storeId(storeId) @@ -264,7 +264,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .storeBenefits(storeBenefits) .guestbookCount(guestbookCount) .likesCount(likesCount) - //.isFavorited(isFavorited) + // .isFavorited(isFavorited) .build(); ApiResponse apiResponse = ApiResponse.builder() From 7a13643810b10fd56bf228dfd14ddcde905d0943 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Tue, 13 Feb 2024 21:07:49 +0900 Subject: [PATCH 246/356] =?UTF-8?q?Chore:=20Likes=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 02791884..928599e3 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -247,7 +247,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .collect(Collectors.toList()); Integer guestbookCount = guestBookRepository.countByStoreId(storeId); Integer likesCount = likesRepository.countByStoreId(storeId); - // Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); + //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() .storeId(storeId) @@ -264,7 +264,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .storeBenefits(storeBenefits) .guestbookCount(guestbookCount) .likesCount(likesCount) - // .isFavorited(isFavorited) + //.isFavorited(isFavorited) .build(); ApiResponse apiResponse = ApiResponse.builder() From 0bd6361c53e4f4efe274ada9a3ffaa300a4f86f2 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Tue, 13 Feb 2024 21:11:50 +0900 Subject: [PATCH 247/356] =?UTF-8?q?Chore:=20Likes=20=EB=A9=A4=EB=B2=84?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/likes/domain/repository/LikesRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index 15a0006e..deb6cb14 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -12,5 +12,5 @@ public interface LikesRepository extends JpaRepository { Integer countByStoreId(Long storeId); - //Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); + //Boolean existsByMemberIdAndStoreId(Long memberId, Long storeId); } From 5510dff22db36e9062a03171ef96872824d2e033 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 16:42:09 +0900 Subject: [PATCH 248/356] =?UTF-8?q?[Feat]=20GuestBook=20domain=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GuestBookService.java | 43 +++++++++++++++++-- .../domain/guestbook/domain/GuestBook.java | 12 ------ .../repository/GuestBookRepository.java | 17 ++++++++ .../request/CreateGuestBookRequestDto.java | 2 - .../InvalidRegisterMemberException.java | 11 +++++ .../domain/spot/application/SpotService.java | 19 ++++++++ .../spot/presentation/SpotController.java | 8 ++-- 7 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/member/exception/InvalidRegisterMemberException.java diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index acc59d1b..b6ee777b 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -23,6 +23,7 @@ import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.InvalidStoreIdException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.tags.Tag; @@ -85,7 +86,7 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { } @Transactional - public ResponseEntity createGuestBook(HttpServletRequest request, Integer spotId, CreateGuestBookRequestDto createGuestBookRequestDto) { + public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuestBookRequestDto createGuestBookRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -93,8 +94,11 @@ public ResponseEntity createGuestBook(HttpServletRequest request, Integer spo GuestBook guestBook; + Spot spot; + Store store; + if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.SPOT)) { - Spot spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); + spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); guestBook = GuestBook.builder() .member(member) @@ -104,8 +108,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, Integer spo .star(createGuestBookRequestDto.getStar()) .build(); } else if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.STORE)) { - // TODO exception 교체 - Store store = storeRepository.findById(createGuestBookRequestDto.getStoreId()).orElseThrow(InvalidSpotIdException::new); + store = storeRepository.findById(createGuestBookRequestDto.getStoreId()).orElseThrow(InvalidStoreIdException::new); guestBook = GuestBook.builder() .member(member) @@ -127,6 +130,38 @@ public ResponseEntity createGuestBook(HttpServletRequest request, Integer spo .build(); imageService.createImage(createImageRequestDto); + if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.SPOT)) { + spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); + + Float originStars = guestBookRepository.sumStarBySpotId(spot.getId()); + + Long guestBookNum = guestBookRepository.countAllBySpot_Id(spot.getId()); + + float updateStarValue; + + updateStarValue = ((originStars * guestBookNum) + createGuestBookRequestDto.getStar()) / (guestBookNum + 1); + + spot.updateStars(updateStarValue); + + spotRepository.save(spot); + } else if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.STORE)) { + store = storeRepository.findById(createGuestBookRequestDto.getStoreId()).orElseThrow(InvalidStoreIdException::new); + + Float originStars = guestBookRepository.sumStarByStoreId(store.getId()); + + Long guestBookNum = guestBookRepository.countAllByStore_Id(store.getId()); + + float updateStarValue; + + updateStarValue = ((originStars * guestBookNum) + createGuestBookRequestDto.getStar()) / (guestBookNum + 1); + + store.updateStars(updateStarValue); + + storeRepository.save(store); + } else { + throw new InvalidGuestBookException(); + } + return getResponseEntity(guestBook); } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java index 802a9efc..4f2bad81 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java @@ -1,20 +1,14 @@ package com.ttubeog.domain.guestbook.domain; import com.ttubeog.domain.common.BaseEntity; -<<<<<<< HEAD import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; -======= -import com.ttubeog.domain.store.domain.Store; -import jakarta.persistence.*; ->>>>>>> dev import lombok.Getter; import lombok.NoArgsConstructor; @@ -31,7 +25,6 @@ public class GuestBook extends BaseEntity { private Long id; @ManyToOne(fetch = FetchType.LAZY) -<<<<<<< HEAD @JoinColumn(name = "member_id", nullable = false) private Member member; @@ -69,9 +62,4 @@ public void updateGuestBook(String content, Float star, Image image) { this.star = star; this.image = image; } - -======= - @JoinColumn(name = "store_id") - private Store store; ->>>>>>> dev } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 92b1d9fa..ea8c61bd 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -2,12 +2,29 @@ import com.ttubeog.domain.guestbook.domain.GuestBook; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface GuestBookRepository extends JpaRepository { + + List findAllBySpot_Id(Long spotId); + + Long countAllBySpot_Id(Long spotId); + + @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.spot.id = :spotId") + Float sumStarBySpotId(@Param("spotId") Long spotId); + + List findAllByStore_Id(Long storeId); + + Long countAllByStore_Id(Long storeId); + + @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.store.id = :storeId") + Float sumStarByStoreId(@Param("storeId") Long storeId); + List findByStoreId(Long storeId); Integer countByStoreId(Long storeId); diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java index c570c8ee..46e24e81 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java @@ -6,8 +6,6 @@ @Getter public class CreateGuestBookRequestDto { - private Long memberId; - private GuestBookType guestBookType; private Long spotId; diff --git a/src/main/java/com/ttubeog/domain/member/exception/InvalidRegisterMemberException.java b/src/main/java/com/ttubeog/domain/member/exception/InvalidRegisterMemberException.java new file mode 100644 index 00000000..0c74ccd6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/exception/InvalidRegisterMemberException.java @@ -0,0 +1,11 @@ +package com.ttubeog.domain.member.exception; + +public class InvalidRegisterMemberException extends RuntimeException { + public InvalidRegisterMemberException() { + super("해당 객체를 등록한 유저가 아닙니다."); + } + + public InvalidRegisterMemberException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index e7b27f68..eae845d6 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -3,6 +3,9 @@ import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.guestbook.application.GuestBookService; +import com.ttubeog.domain.guestbook.domain.GuestBook; +import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.ImageType; @@ -11,6 +14,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.member.exception.InvalidRegisterMemberException; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; @@ -42,6 +46,8 @@ public class SpotService { private final MemberRepository memberRepository; private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; + private final GuestBookRepository guestBookRepository; + private final GuestBookService guestBookService; private final ImageService imageService; @@ -143,6 +149,10 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd // 존재하는 산책 스팟을 수정하려는지 체크 Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + if (spot.getMember().getId().equals(memberId)) { + throw new InvalidRegisterMemberException("해당 산책 스팟을 등록한 유저가 아닙니다."); + } + // 수정하려는 이름과 중복된 이름을 가진 산책 스팟이 있는지 if (spotRepository.findByName(updateSpotRequestDto.getName()).isPresent()) { Spot duplicateSpot = spotRepository.findByName(updateSpotRequestDto.getName()).orElseThrow(InvalidSpotIdException::new); @@ -193,6 +203,10 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + if (spot.getMember().getId().equals(memberId)) { + throw new InvalidRegisterMemberException("해당 산책 스팟을 등록한 유저가 아닙니다."); + } + spotRepository.delete(spot); List imageList = imageRepository.findBySpotId(spot.getId()); @@ -200,6 +214,11 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { imageService.deleteImage(image.getId()); } + List guestBookList = guestBookRepository.findAllBySpot_Id(spotId); + for (GuestBook guestBook : guestBookList) { + guestBookService.deleteGuestBook(request, guestBook.getId()); + } + ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("산책 스팟을 삭제햇습니다.").build()) diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 201c6ee0..f9cbc974 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -323,7 +323,6 @@ public ResponseEntity deleteSpot( /** * 산책 스팟 방명록 작성 API * @param request 유저 검증 - * @param spotId 산책 스팟 ID * @param createGuestBookRequestDto 방명록 작성 DTO * @return ResponseEntity -> GuestBookResponseDto * @throws JsonProcessingException JSON Processing 에러 @@ -332,12 +331,12 @@ public ResponseEntity deleteSpot( description = "산책 스팟을 방명록을 작성합니다.\n" + "GuestBook(방명록) 기능 미구현.", responses = {@ApiResponse( - responseCode = "200", + responseCode = "201", description = "OK", content = { @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + array = @ArraySchema(schema = @Schema(implementation = GuestBookService.class)) ) } ), @@ -386,10 +385,9 @@ public ResponseEntity deleteSpot( @PostMapping("/{spotId}/guestbook") public ResponseEntity createGuestBook( @CurrentUser HttpServletRequest request, - @RequestParam(name = "spotId") Integer spotId, @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto ) throws JsonProcessingException { - return guestBookService.createGuestBook(request, spotId, createGuestBookRequestDto); + return guestBookService.createGuestBook(request, createGuestBookRequestDto); } /** From aa9c3a555b2e0a9520b88823757ce5c66f7196c8 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 17:00:19 +0900 Subject: [PATCH 249/356] [Feat] add findGuestBookByPlaceId method to GuestBook Service --- .../application/GuestBookService.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index b6ee777b..a21e163c 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -26,6 +26,7 @@ import com.ttubeog.domain.store.exception.InvalidStoreIdException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; +import feign.Response; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; @@ -35,6 +36,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -176,6 +179,64 @@ public ResponseEntity findByGuestBookId(HttpServletRequest request, Long gues return getResponseEntity(guestBook); } + public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId) { + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + List guestBookList = guestBookRepository.findAllBySpot_Id(spotId); + + List guestBookResponseDtoList = null; + + for (GuestBook guestBook : guestBookList) { + GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .spotId(guestBook.getSpot().getId()) + .memberId(guestBook.getMember().getId()) + .star(guestBook.getStar()) + .build(); + guestBookResponseDtoList.add(guestBookResponseDto); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(guestBookResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId) { + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + List guestBookList = guestBookRepository.findAllByStore_Id(storeId); + + List guestBookResponseDtoList = null; + + for (GuestBook guestBook : guestBookList) { + GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .spotId(guestBook.getSpot().getId()) + .memberId(guestBook.getMember().getId()) + .star(guestBook.getStar()) + .build(); + guestBookResponseDtoList.add(guestBookResponseDto); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(guestBookResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + @Transactional public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestBookId, UpdateGuestBookRequestDto updateGuestBookRequestDto) { From 533d5169b2e374648e587eb613c7dd06ae7780b1 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 17:07:07 +0900 Subject: [PATCH 250/356] [Feat] add Road Domain Files --- .../ttubeog/domain/road/dto/request/CreateRoadRequestDto.java | 4 ++++ .../com/ttubeog/domain/road/dto/response/RoadResponseDto.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java new file mode 100644 index 00000000..04d23fa4 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.road.dto.request; + +public class CreateRoadRequestDto { +} diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java new file mode 100644 index 00000000..907f2d6c --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.road.dto.response; + +public class RoadResponseDto { +} From 7834d73a85b451916b0e472cdb4de73dff0b569f Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 17:48:28 +0900 Subject: [PATCH 251/356] [Feat] implement Road Entity --- .../com/ttubeog/domain/road/domain/Road.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index efc2bdcd..b289220d 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -1,10 +1,10 @@ package com.ttubeog.domain.road.domain; import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; @Entity public class Road extends BaseEntity { @@ -12,4 +12,25 @@ public class Road extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "spot_id") + private Spot spot; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "road_file", nullable = false) + private String roadFile; + + @Column(name = "time", nullable = false) + private String time; } From 2cbffd67f7d8ebdcfc620e4945d9bcd2e04743d0 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 20:34:37 +0900 Subject: [PATCH 252/356] [Chore] edit Swagger Http Response code --- .../com/ttubeog/domain/spot/presentation/SpotController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index f9cbc974..2360d64b 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -331,7 +331,7 @@ public ResponseEntity deleteSpot( description = "산책 스팟을 방명록을 작성합니다.\n" + "GuestBook(방명록) 기능 미구현.", responses = {@ApiResponse( - responseCode = "201", + responseCode = "200", description = "OK", content = { @Content( From 08312b62612a56a3bedb7b8ad6884a9a7203d07b Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 20:43:20 +0900 Subject: [PATCH 253/356] =?UTF-8?q?[Chore]=20GuestBook=20Service=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/application/GuestBookService.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index a21e163c..d886357b 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -53,6 +53,8 @@ public class GuestBookService { private final JwtTokenProvider jwtTokenProvider; + + // ResponseEntity 형식에 맞춰 빌드하는 메서드 @NonNull private ResponseEntity getResponseEntity(GuestBook guestBook) { @@ -88,6 +90,8 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { return ResponseEntity.ok(apiResponse); } + // GuestBook(방명록) 을 하나 생성하는 Service Method 입니다. + // Spot 이나 Store Controller 혹은 Service 단에서 불러와서 사용 가능합니다. @Transactional public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuestBookRequestDto createGuestBookRequestDto) { @@ -169,6 +173,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest } + // GuestBook 을 Id(PK) 값으로 찾는 Method 입니다. 현재 사용하지 않습니다. public ResponseEntity findByGuestBookId(HttpServletRequest request, Long guestBookId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -179,6 +184,7 @@ public ResponseEntity findByGuestBookId(HttpServletRequest request, Long gues return getResponseEntity(guestBook); } + // Spot ID 로 GuestBook 을 조회하는 Method 입니다. 현재 따로 사용하지 않습니다. public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -208,6 +214,7 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long return ResponseEntity.ok(apiResponse); } + // Store ID 로 GuestBook 을 조회하는 Method 입니다. 현재 따로 사용하지 않습니다. public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -238,6 +245,7 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long } + // GuestBook 을 Update 하는 Method 입니다. 현재 따로 사용하지 않습니다. @Transactional public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestBookId, UpdateGuestBookRequestDto updateGuestBookRequestDto) { @@ -266,6 +274,7 @@ public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestB return getResponseEntity(guestBook); } + // GuestBook 을 하나 Delete 하는 Method 입니다. @Transactional public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestBookId) { Long memberId = jwtTokenProvider.getMemberId(request); From 63c23fbc65c563220e89e238979f5d9eeb3c396a Mon Sep 17 00:00:00 2001 From: Dustbox Date: Thu, 15 Feb 2024 21:06:21 +0900 Subject: [PATCH 254/356] =?UTF-8?q?[Chore]=20guestbookRepository=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20Store/Spot=20Service=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guestbook/domain/repository/GuestBookRepository.java | 3 --- .../com/ttubeog/domain/spot/application/SpotService.java | 8 ++------ .../ttubeog/domain/store/application/StoreService.java | 4 ++-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index ea8c61bd..3bb0a2f5 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -25,7 +25,4 @@ public interface GuestBookRepository extends JpaRepository { @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.store.id = :storeId") Float sumStarByStoreId(@Param("storeId") Long storeId); - List findByStoreId(Long storeId); - - Integer countByStoreId(Long storeId); } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index eae845d6..151f5b6e 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -210,14 +210,10 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { spotRepository.delete(spot); List imageList = imageRepository.findBySpotId(spot.getId()); - for (Image image : imageList) { - imageService.deleteImage(image.getId()); - } + imageRepository.deleteAll(imageList); List guestBookList = guestBookRepository.findAllBySpot_Id(spotId); - for (GuestBook guestBook : guestBookList) { - guestBookService.deleteGuestBook(request, guestBook.getId()); - } + guestBookRepository.deleteAll(guestBookList); ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 928599e3..06310cad 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -210,7 +210,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { benefitRepository.deleteAll(benefits); // 해당 매장과 연관된 방명록 삭제 - List guestBooks = guestBookRepository.findByStoreId(storeId); + List guestBooks = guestBookRepository.findAllByStore_Id(storeId); guestBookRepository.deleteAll(guestBooks); // 해당 매장과 연관된 좋아요 삭제 @@ -245,7 +245,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .stream() .map(Benefit::getType) .collect(Collectors.toList()); - Integer guestbookCount = guestBookRepository.countByStoreId(storeId); + Integer guestbookCount = guestBookRepository.countAllByStore_Id(storeId).intValue(); Integer likesCount = likesRepository.countByStoreId(storeId); //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); From 17e6100c0f1c6bf9ab884de43fc6ff01625135f1 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 02:36:43 +0900 Subject: [PATCH 255/356] =?UTF-8?q?[Feat]=20Benefit-Store=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 10 ++++- .../domain/repository/BenefitRepository.java | 5 ++- .../repository/MemberBenefitRepository.java | 2 +- .../benefit/dto/response/SaveBenefitRes.java | 10 ++++- .../domain/game/application/GameService.java | 43 ++++++++++++++++++- .../game/dto/request/CreateBasketballReq.java | 3 +- .../game/dto/request/CreateGiftReq.java | 3 +- .../game/dto/request/CreateRouletteReq.java | 3 +- .../game/dto/request/UpdateBasketballReq.java | 3 ++ .../game/dto/request/UpdateGiftReq.java | 3 ++ .../game/dto/request/UpdateRouletteReq.java | 3 ++ .../dto/response/CreateBasketballRes.java | 6 ++- .../game/dto/response/CreateGiftRes.java | 6 ++- .../game/dto/response/CreateRouletteRes.java | 6 ++- .../domain/game/dto/response/FindGameRes.java | 4 +- .../dto/response/UpdateBasketballRes.java | 6 ++- .../game/dto/response/UpdateGiftRes.java | 6 ++- .../game/dto/response/UpdateRouletteRes.java | 6 ++- .../exception/AlreadyExistGameException.java | 7 +++ .../store/application/StoreService.java | 6 +-- 20 files changed, 118 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/game/exception/AlreadyExistGameException.java diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index cf7bcb49..a88e097a 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -16,6 +16,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; @@ -50,9 +51,10 @@ public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); + List checkBenefitList = benefitRepository.findByStore(benefit.getStore()); //같은 benefit이고, 저장한지 한달이 지나지 않았으면 에러 호출 - if (memberBenefitRepository.existsByBenefitAndCreatedAtIsAfter(benefit, LocalDateTime.now().minusMonths(1))) { + if (memberBenefitRepository.existsByBenefitInAndMemberAndCreatedAtIsAfter(checkBenefitList, member, LocalDateTime.now().minusMonths(1))) { throw new OverlappingBenefitException(); } @@ -68,6 +70,8 @@ public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(benefit.getId()) + .storeId(benefit.getStore().getId()) + .storeName(benefit.getStore().getName()) .content(benefit.getContent()) .type(benefit.getType()) .used(memberBenefit.getUsed()) @@ -105,6 +109,8 @@ public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) SaveBenefitRes saveBenefitRes = SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(benefit.getId()) + .storeId(benefit.getStore().getId()) + .storeName(benefit.getStore().getName()) .used(memberBenefit.getUsed()) .expried(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) @@ -131,6 +137,8 @@ public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) memberBenefit -> SaveBenefitRes.builder() .id(memberBenefit.getId()) .benefitId(memberBenefit.getBenefit().getId()) + .storeId(memberBenefit.getBenefit().getStore().getId()) + .storeName(memberBenefit.getBenefit().getStore().getName()) .used(memberBenefit.getUsed()) .expried(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java index a87eebe2..788f2a6b 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/BenefitRepository.java @@ -2,6 +2,7 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.game.domain.Game; +import com.ttubeog.domain.store.domain.Store; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -15,5 +16,7 @@ public interface BenefitRepository extends JpaRepository { List findAllByGame(Game game); - List findByStoreId(Long storeId); + List findByStore(Store store); + + List findAllByStoreAndGameIsNotNull(Store store); } diff --git a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java index 8859fba3..d6712f07 100644 --- a/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java +++ b/src/main/java/com/ttubeog/domain/benefit/domain/repository/MemberBenefitRepository.java @@ -15,7 +15,7 @@ @Repository public interface MemberBenefitRepository extends JpaRepository { - Boolean existsByBenefitAndCreatedAtIsAfter(Benefit benefit, LocalDateTime createdAt); + Boolean existsByBenefitInAndMemberAndCreatedAtIsAfter(List benefitList, Member member, LocalDateTime createdAt); Optional findByBenefitAndMemberAndExpiredIsFalse(Benefit benefit, Member member); diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java index 5005d763..721cd729 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -16,6 +16,12 @@ public class SaveBenefitRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; + @Schema(description = "매장 ID", example = "1") + private Long storeId; + + @Schema(description = "매장 이름", example = "맥도날드") + private String storeName; + @Schema(description = "내용", example = "아메리카노 20% 할인") private String content; @@ -32,9 +38,11 @@ public class SaveBenefitRes { private LocalDateTime createdAt; @Builder - public SaveBenefitRes(Long id, Long benefitId, String content, BenefitType type, Boolean used, Boolean expried, LocalDateTime createdAt) { + public SaveBenefitRes(Long id, Long benefitId, Long storeId, String storeName, String content, BenefitType type, Boolean used, Boolean expried, LocalDateTime createdAt) { this.id = id; this.benefitId = benefitId; + this.storeId = storeId; + this.storeName = storeName; this.content = content; this.type = type; this.used = used; diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index a617640d..cb2c4251 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -12,10 +12,14 @@ import com.ttubeog.domain.game.domain.repository.*; import com.ttubeog.domain.game.dto.request.*; import com.ttubeog.domain.game.dto.response.*; +import com.ttubeog.domain.game.exception.AlreadyExistGameException; import com.ttubeog.domain.game.exception.NonExistentGameException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.InvalidStoreIdException; import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; @@ -26,7 +30,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.HashSet; import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; @RequiredArgsConstructor @@ -41,6 +48,7 @@ public class GameService { private final BasketBallRepository basketBallRepository; private final RouletteRepository rouletteRepository; private final MemberBenefitRepository memberBenefitRepository; + private final StoreRepository storeRepository; private final JwtTokenProvider jwtTokenProvider; // 선물게임 생성 @@ -48,8 +56,13 @@ public class GameService { public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(createGiftReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); - //TODO 연결 후 store에 이미 존재하는 gametype인지 확인 + //store에 이미 존재하는 gametype인지 확인 + List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); + if (checkBenefitList.stream().anyMatch(benefit -> GameType.GIFT.equals(benefit.getGame().getType()))) { + throw new AlreadyExistGameException(); + } Game game = Game.builder() .type(GameType.GIFT) @@ -58,6 +71,7 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr gameRepository.save(game); Benefit benefit = Benefit.builder() + .store(store) .content(createGiftReq.getBenefitContent()) .type(createGiftReq.getBenefitType()) .game(game) @@ -76,6 +90,7 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr CreateGiftRes createGiftRes = CreateGiftRes.builder() .gameId(game.getId()) .benefitId(benefit.getId()) + .storeId(store.getId()) .giftCount(giftGame.getGiftCount()) .timeLimit(giftGame.getTimeLimit()) .benefitType(benefit.getType()) @@ -95,6 +110,13 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr public ResponseEntity createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(createBasketballReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); + + //store에 이미 존재하는 gametype인지 확인 + List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); + if (checkBenefitList.stream().anyMatch(benefit -> GameType.BASKETBALL.equals(benefit.getGame().getType()))) { + throw new AlreadyExistGameException(); + } Game game = Game.builder() .type(GameType.BASKETBALL) @@ -103,6 +125,7 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask gameRepository.save(game); Benefit benefit = Benefit.builder() + .store(store) .content(createBasketballReq.getBenefitContent()) .type(createBasketballReq.getBenefitType()) .game(game) @@ -122,6 +145,7 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask CreateBasketballRes createBasketballRes = CreateBasketballRes.builder() .gameId(game.getId()) .benefitId(benefit.getId()) + .storeId(store.getId()) .timeLimit(basketballGame.getTimeLimit()) .ballCount(basketballGame.getBallCount()) .successCount(basketballGame.getSuccessCount()) @@ -142,6 +166,13 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask public ResponseEntity createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(createRouletteReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); + + //store에 이미 존재하는 gametype인지 확인 + List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); + if (checkBenefitList.stream().anyMatch(benefit -> GameType.ROULETTE.equals(benefit.getGame().getType()))) { + throw new AlreadyExistGameException(); + } Game game = Game.builder() .type(GameType.ROULETTE) @@ -150,6 +181,7 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet List benefitList = createRouletteReq.getOptions().stream() .map(option -> Benefit.builder() + .store(store) .content(option) .type(createRouletteReq.getBenefitType()) .game(game) @@ -174,6 +206,7 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet CreateRouletteRes createRouletteRes = CreateRouletteRes.builder() .gameId(rouletteGame.getId()) + .storeId(store.getId()) .benefits(benefitResDtoList) .options(rouletteGame.getOptions()) .build(); @@ -194,11 +227,13 @@ public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq up GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); + Store store = storeRepository.findById(updateGiftReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); giftGame.updateGiftCount(updateGiftReq.getGiftCount()); Benefit newBenefit = Benefit.builder() + .store(store) .game(giftGame.getGame()) .type(updateGiftReq.getBenefitType()) .content(updateGiftReq.getBenefitContent()) @@ -230,12 +265,14 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); + Store store = storeRepository.findById(updateBasketballReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); basketballGame.updateTimeLimit(updateBasketballReq.getTimeLimit()); Benefit newBenefit = Benefit.builder() + .store(store) .game(basketballGame.getGame()) .type(updateBasketballReq.getBenefitType()) .content(updateBasketballReq.getBenefitContent()) @@ -244,6 +281,7 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask UpdateBasketballRes updateBasketballRes = UpdateBasketballRes.builder() .gameId(basketballGame.getId()) + .storeId(store.getId()) .ballCount(basketballGame.getBallCount()) .timeLimit(basketballGame.getTimeLimit()) .successCount(basketballGame.getSuccessCount()) @@ -268,9 +306,11 @@ public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRoulet RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(rouletteGame.getGame()); benefitList.forEach(benefit -> benefit.deleteGame()); + Store store = storeRepository.findById(updateRouletteReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); List newBenefitList = updateRouletteReq.getOptions().stream() .map(option -> Benefit.builder() + .store(store) .content(option) .type(updateRouletteReq.getBenefitType()) .game(rouletteGame.getGame()) @@ -291,6 +331,7 @@ public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRoulet UpdateRouletteRes updateRouletteRes = UpdateRouletteRes.builder() .gameId(rouletteGame.getId()) + .storeId(store.getId()) .options(rouletteGame.getOptions()) .benefits(benefitResDtoList) .build(); diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java index 9c553846..578c6d9e 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java @@ -10,7 +10,8 @@ @Schema(description = "CreateBasketballGameRequest") public class CreateBasketballReq { -// private Long StoreId; + @Schema(description = "매장ID", example = "1") + private Long storeId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java index fe7a1ce1..89e15d41 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java @@ -10,7 +10,8 @@ @Schema(description = "CreateGiftGameRequest") public class CreateGiftReq { - // private Long StoreId; + @Schema(description = "매장ID", example = "1") + private Long storeId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java index 5393fe6e..74198cd6 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateRouletteReq.java @@ -10,7 +10,8 @@ @Schema(description = "CreateRouletteGameRequest") public class CreateRouletteReq { - //private Long storeId + @Schema(description = "매장ID", example = "1") + private Long storeId; @Schema(description = "혜택 타입", example = "SALE") private BenefitType benefitType; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java index 963bf7c6..272a1ed9 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -13,6 +13,9 @@ public class UpdateBasketballReq { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java index ced4904a..1287f955 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -13,6 +13,9 @@ public class UpdateGiftReq { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java index 570f3857..5ca9cb02 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java @@ -12,6 +12,9 @@ public class UpdateRouletteReq { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "혜택 타입", example = "SALE") private BenefitType benefitType; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java index b02fd694..312a2d50 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java @@ -16,7 +16,8 @@ public class CreateBasketballRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; - // private Long StoreId; + @Schema(description = "매장ID", example = "1") + private Long storeId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -34,9 +35,10 @@ public class CreateBasketballRes { private BenefitType benefitType; @Builder - public CreateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public CreateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; + this.storeId = storeId; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java index 5de8eb64..0267062d 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -16,7 +16,8 @@ public class CreateGiftRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; - // private Long StoreId; + @Schema(description = "매장ID", example = "1") + private Long storeId; @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -31,9 +32,10 @@ public class CreateGiftRes { private BenefitType benefitType; @Builder - public CreateGiftRes(Long benefitId, Long gameId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public CreateGiftRes(Long benefitId, Long gameId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.benefitId = benefitId; this.gameId = gameId; + this.storeId = storeId; this.timeLimit = timeLimit; this.giftCount = giftCount; this.benefitContent = benefitContent; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java index 5c9eb32c..24e11083 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -15,13 +15,15 @@ public class CreateRouletteRes { @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; - //private Long storeId; + @Schema(description = "매장ID", example = "1") + private Long storeId; private List benefits; @Builder - public CreateRouletteRes(Long gameId, List options, List benefits) { + public CreateRouletteRes(Long gameId, Long storeId, List options, List benefits) { this.gameId = gameId; + this.storeId = storeId; this.options = options; this.benefits = benefits; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 67afa7f7..883fb67c 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -14,8 +14,6 @@ public class FindGameRes { @Schema(description = "게임 ID", example = "1") private Long gameId; - //private Long storeId; - @Schema(description = "종류", example = "roulette") private GameType type; @@ -35,7 +33,7 @@ public class FindGameRes { private List options; @Builder - public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { + public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { this.gameId = gameId; this.type = type; this.timeLimit = timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java index 2038fbc9..b17a08bd 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java @@ -16,6 +16,9 @@ public class UpdateBasketballRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -32,9 +35,10 @@ public class UpdateBasketballRes { private BenefitType benefitType; @Builder - public UpdateBasketballRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public UpdateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; + this.storeId = storeId; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java index 593a3df1..827e335b 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java @@ -16,6 +16,9 @@ public class UpdateGiftRes { @Schema(description = "혜택 ID", example = "1") private Long benefitId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "시간제한", example = "00:01:30") private LocalTime timeLimit; @@ -29,9 +32,10 @@ public class UpdateGiftRes { private BenefitType benefitType; @Builder - public UpdateGiftRes(Long gameId, Long benefitId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public UpdateGiftRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; + this.storeId = storeId; this.timeLimit = timeLimit; this.giftCount = giftCount; this.benefitContent = benefitContent; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java index ef6e598a..d17e2148 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java @@ -13,14 +13,18 @@ public class UpdateRouletteRes { @Schema(description = "게임 ID", example = "1") private Long gameId; + @Schema(description = "매장ID", example = "1") + private Long storeId; + @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; private List benefits; @Builder - public UpdateRouletteRes(Long gameId, List options, List benefits) { + public UpdateRouletteRes(Long gameId, Long storeId, List options, List benefits) { this.gameId = gameId; + this.storeId = storeId; this.options = options; this.benefits = benefits; } diff --git a/src/main/java/com/ttubeog/domain/game/exception/AlreadyExistGameException.java b/src/main/java/com/ttubeog/domain/game/exception/AlreadyExistGameException.java new file mode 100644 index 00000000..04ee9fcb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/game/exception/AlreadyExistGameException.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.game.exception; + +public class AlreadyExistGameException extends RuntimeException{ + public AlreadyExistGameException() { + super("해당 매장에 이미 같은 종류의 게임이 존재합니다."); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 928599e3..e7c108f6 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -199,14 +199,14 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { } // 특정 유저가 가진 해당 매장의 혜택 삭제 - List benefitsToDelete = benefitRepository.findByStoreId(storeId); + List benefitsToDelete = benefitRepository.findByStore(store); for (Benefit benefit : benefitsToDelete) { List memberBenefits = memberBenefitRepository.findByBenefitId(benefit.getId()); memberBenefitRepository.deleteAll(memberBenefits); } // 해당 매장과 연관된 혜택 삭제 - List benefits = benefitRepository.findByStoreId(storeId); + List benefits = benefitRepository.findByStore(store); benefitRepository.deleteAll(benefits); // 해당 매장과 연관된 방명록 삭제 @@ -241,7 +241,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); - List storeBenefits = benefitRepository.findByStoreId(storeId) + List storeBenefits = benefitRepository.findByStore(store) .stream() .map(Benefit::getType) .collect(Collectors.toList()); From deff1d9b3f41845afd523ec7162036cb359c5c66 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 02:43:52 +0900 Subject: [PATCH 256/356] =?UTF-8?q?[Refac]=20=ED=8F=89=EC=A0=90=20Update?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20GuestB?= =?UTF-8?q?ook=20Controller=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GuestBookService.java | 26 +++-- .../domain/guestbook/domain/GuestBook.java | 7 +- .../repository/GuestBookRepository.java | 7 ++ .../dto/response/GuestBookResponseDto.java | 6 +- .../presentation/GuestBookController.java | 102 +++++++++++++++++- .../spot/presentation/SpotController.java | 69 ------------ 6 files changed, 126 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index d886357b..563e348a 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -28,14 +28,18 @@ import com.ttubeog.global.payload.Message; import feign.Response; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.apache.ibatis.jdbc.Null; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.awt.print.Pageable; import java.util.List; @RequiredArgsConstructor @@ -130,6 +134,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest guestBookRepository.save(guestBook); + CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() .image(createGuestBookRequestDto.getImage()) .imageType(ImageType.GUESTBOOK) @@ -137,6 +142,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest .build(); imageService.createImage(createImageRequestDto); + if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.SPOT)) { spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); @@ -146,7 +152,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest float updateStarValue; - updateStarValue = ((originStars * guestBookNum) + createGuestBookRequestDto.getStar()) / (guestBookNum + 1); + updateStarValue = ((originStars + (float)createGuestBookRequestDto.getStar()) / (float)(guestBookNum + 1)); spot.updateStars(updateStarValue); @@ -160,7 +166,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest float updateStarValue; - updateStarValue = ((originStars * guestBookNum) + createGuestBookRequestDto.getStar()) / (guestBookNum + 1); + updateStarValue = ((originStars + (float)createGuestBookRequestDto.getStar()) / (float)(guestBookNum + 1)); store.updateStars(updateStarValue); @@ -184,17 +190,17 @@ public ResponseEntity findByGuestBookId(HttpServletRequest request, Long gues return getResponseEntity(guestBook); } - // Spot ID 로 GuestBook 을 조회하는 Method 입니다. 현재 따로 사용하지 않습니다. - public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId) { + // Spot ID 로 GuestBook 을 조회하는 Method 입니다. + public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List guestBookList = guestBookRepository.findAllBySpot_Id(spotId); + Page guestBookPage = guestBookRepository.findAllBySpot_Id(spotId, PageRequest.of(pageNum, 10)); List guestBookResponseDtoList = null; - for (GuestBook guestBook : guestBookList) { + for (GuestBook guestBook : guestBookPage) { GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() .id(guestBook.getId()) .content(guestBook.getContent()) @@ -214,17 +220,17 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long return ResponseEntity.ok(apiResponse); } - // Store ID 로 GuestBook 을 조회하는 Method 입니다. 현재 따로 사용하지 않습니다. - public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId) { + // Store ID 로 GuestBook 을 조회하는 Method 입니다. + public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - List guestBookList = guestBookRepository.findAllByStore_Id(storeId); + Page guestBookPage = guestBookRepository.findAllByStore_Id(storeId, PageRequest.of(pageNum, 10)); List guestBookResponseDtoList = null; - for (GuestBook guestBook : guestBookList) { + for (GuestBook guestBook : guestBookPage) { GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() .id(guestBook.getId()) .content(guestBook.getContent()) diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java index 4f2bad81..fd435ca2 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBook.java @@ -43,10 +43,7 @@ public class GuestBook extends BaseEntity { private Float star; - @OneToOne(mappedBy = "guestBook", cascade = CascadeType.ALL) - private Image image; - - public GuestBook(Long id, Member member, GuestBookType guestBookType, Spot spot, Store store, String content, Float star, Image image) { + public GuestBook(Long id, Member member, GuestBookType guestBookType, Spot spot, Store store, String content, Float star) { this.id = id; this.member = member; this.guestBookType = guestBookType; @@ -54,12 +51,10 @@ public GuestBook(Long id, Member member, GuestBookType guestBookType, Spot spot, this.store = store; this.content = content; this.star = star; - this.image = image; } public void updateGuestBook(String content, Float star, Image image) { this.content = content; this.star = star; - this.image = image; } } diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 3bb0a2f5..15d769da 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -1,11 +1,14 @@ package com.ttubeog.domain.guestbook.domain.repository; import com.ttubeog.domain.guestbook.domain.GuestBook; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.awt.print.Pageable; import java.util.List; @Repository @@ -13,6 +16,8 @@ public interface GuestBookRepository extends JpaRepository { List findAllBySpot_Id(Long spotId); + Page findAllBySpot_Id(Long spotId, PageRequest pageRequest); + Long countAllBySpot_Id(Long spotId); @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.spot.id = :spotId") @@ -20,6 +25,8 @@ public interface GuestBookRepository extends JpaRepository { List findAllByStore_Id(Long storeId); + Page findAllByStore_Id(Long storeId, PageRequest pageRequest); + Long countAllByStore_Id(Long storeId); @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.store.id = :storeId") diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java index 6f8e4495..1643090a 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java @@ -24,10 +24,7 @@ public class GuestBookResponseDto { private Float star; - private String image; - - - public GuestBookResponseDto(Long id, Long memberId, GuestBookType guestBookType, Long spotId, Long storeId, String content, Float star, String image) { + public GuestBookResponseDto(Long id, Long memberId, GuestBookType guestBookType, Long spotId, Long storeId, String content, Float star) { this.id = id; this.memberId = memberId; this.guestBookType = guestBookType; @@ -35,6 +32,5 @@ public GuestBookResponseDto(Long id, Long memberId, GuestBookType guestBookType, this.storeId = storeId; this.content = content; this.star = star; - this.image = image; } } diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 4b317aa3..30307c64 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -1,8 +1,108 @@ package com.ttubeog.domain.guestbook.presentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.guestbook.application.GuestBookService; +import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; +import com.ttubeog.domain.guestbook.dto.response.GuestBookResponseDto; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; +import com.ttubeog.domain.spot.dto.response.SpotResponseDto; +import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; +import com.ttubeog.domain.spot.exception.InvalidDongAreaException; +import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; +import com.ttubeog.global.config.security.token.CurrentUser; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +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.tags.Tag; -import org.springframework.web.bind.annotation.RestController; +import jakarta.persistence.Table; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +@Tag(name = "GuestBook", description = "GuestBook API(방명록 API)") +@RequiredArgsConstructor @RestController +@RequestMapping("api/v1/guestbook") public class GuestBookController { + + private final GuestBookService guestBookService; + + /** + * 방명록 생성 API + * @param request 유저 검증 + * @param createGuestBookRequestDto 방명록 생성 DTO + * @return ResponseEntity -> GuestBookResponseDto + * @throws JsonProcessingException json processing 에러 + */ + @Operation(summary = "산책 스팟 생성", + description = "산책 스팟을 생성합니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = GuestBookResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) + @PostMapping + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createGuestBook( + @CurrentUser HttpServletRequest request, + @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto + ) throws JsonProcessingException { + return guestBookService.createGuestBook(request, createGuestBookRequestDto); + } + + + + @GetMapping("/{spotId}&{pageNum}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findGuestBookBySpotId( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "spotId") Long spotId, + @RequestParam(name = "pageNum") Integer pageNum + ) throws JsonProcessingException { + return guestBookService.findGuestBookBySpotId(request, spotId, pageNum); + } + + + @GetMapping("/{storeId}&{pageNum}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findGuestBookByStoreId( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "storeId") Long storeId, + @RequestParam(name = "pageNum") Integer pageNum + ) throws JsonProcessingException { + return guestBookService.findGuestBookByStoreId(request, storeId, pageNum); + } + + + @DeleteMapping("/{guestBookId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteGuestBook( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "guestBookId") Long guestBookId + ) throws JsonProcessingException { + return guestBookService.deleteGuestBook(request, guestBookId); + } + } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 2360d64b..c9a3befe 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -320,75 +320,6 @@ public ResponseEntity deleteSpot( } - /** - * 산책 스팟 방명록 작성 API - * @param request 유저 검증 - * @param createGuestBookRequestDto 방명록 작성 DTO - * @return ResponseEntity -> GuestBookResponseDto - * @throws JsonProcessingException JSON Processing 에러 - */ - @Operation(summary = "산책 스팟 방명록 작성", - description = "산책 스팟을 방명록을 작성합니다.\n" + - "GuestBook(방명록) 기능 미구현.", - responses = {@ApiResponse( - responseCode = "200", - description = "OK", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = GuestBookService.class)) - ) - } - ), - @ApiResponse( - responseCode = "500 - InvalidMemberException", - description = "멤버가 올바르지 않습니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) - ) - } - ), - @ApiResponse( - responseCode = "500 - AlreadyExistsSpotException", - description = "이미 존재하는 산책 장소명입니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) - ) - } - ), - @ApiResponse( - responseCode = "500 - InvalidDongAreaException", - description = "유효하지 않은 지역 정보입니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) - ) - } - ), - @ApiResponse( - responseCode = "500 - InvalidImageListSizeException", - description = "유효하지 않은 이미지 개수입니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = InvalidImageListSizeException.class)) - ) - } - ) - } - ) - @PostMapping("/{spotId}/guestbook") - public ResponseEntity createGuestBook( - @CurrentUser HttpServletRequest request, - @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto - ) throws JsonProcessingException { - return guestBookService.createGuestBook(request, createGuestBookRequestDto); - } /** * 산책 스팟 좋아요 누르기 API From bcbb5d16e39ed60eeff8b96ab9544b944daa086c Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 02:46:50 +0900 Subject: [PATCH 257/356] =?UTF-8?q?[Chore]=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/application/GuestBookService.java | 5 ----- .../guestbook/domain/repository/GuestBookRepository.java | 1 - .../domain/guestbook/presentation/GuestBookController.java | 6 ------ .../ttubeog/domain/spot/presentation/SpotController.java | 2 -- 4 files changed, 14 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 563e348a..6c7d3d84 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -26,20 +26,15 @@ import com.ttubeog.domain.store.exception.InvalidStoreIdException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; -import feign.Response; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import org.apache.ibatis.jdbc.Null; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.awt.print.Pageable; import java.util.List; @RequiredArgsConstructor diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 15d769da..0aac0e2d 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -8,7 +8,6 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.awt.print.Pageable; import java.util.List; @Repository diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 30307c64..ede1b7b4 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -5,11 +5,6 @@ import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; import com.ttubeog.domain.guestbook.dto.response.GuestBookResponseDto; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; -import com.ttubeog.domain.spot.dto.response.SpotResponseDto; -import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; -import com.ttubeog.domain.spot.exception.InvalidDongAreaException; -import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.global.config.security.token.CurrentUser; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -17,7 +12,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.persistence.Table; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index c9a3befe..9f95a2e0 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.guestbook.application.GuestBookService; -import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.application.SpotService; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; @@ -31,7 +30,6 @@ public class SpotController { private final SpotService spotService; - private final GuestBookService guestBookService; /** From 10bd8910e55762a2f19588e7b24f87c2d1f26650 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 02:55:26 +0900 Subject: [PATCH 258/356] =?UTF-8?q?[Feat]=20=EC=9E=A5=EC=86=8C=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 85 +++++++++++++++++-- .../place/dto/request/SearchPlaceReq.java | 14 +++ .../place/dto/response/GetAllPlaceRes.java | 6 +- .../place/dto/response/SearchPlaceRes.java | 63 ++++++++++++++ .../place/presentation/PlaceController.java | 30 ++++++- 5 files changed, 185 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java create mode 100644 src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 7ab7da36..72bec486 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -9,7 +9,9 @@ import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.place.domain.PlaceType; import com.ttubeog.domain.place.dto.request.GetNearbyPlaceReq; +import com.ttubeog.domain.place.dto.request.SearchPlaceReq; import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; +import com.ttubeog.domain.place.dto.response.SearchPlaceRes; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.store.domain.Store; @@ -24,10 +26,13 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import static com.ttubeog.domain.image.application.ImageService.getImageString; + @RequiredArgsConstructor @Service @@ -55,8 +60,8 @@ public List getAllPlaceResList(HttpServletRequest request, Pagea List stores = storeRepository.findAll(); places.addAll(stores.stream().map(store -> mapStoreToDto(request, store)).collect(Collectors.toList())); - // List spots = spotRepository.findAll(); - // places.addAll(spots.stream().map(this::mapSpotToDto).collect(Collectors.toList())); + List spots = spotRepository.findAll(); + places.addAll(spots.stream().map(spot -> mapSpotToDto(request, spot)).collect(Collectors.toList())); int page = pageable.getPageNumber(); int size = pageable.getPageSize(); @@ -87,9 +92,9 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { .build(); } - /*private GetAllPlaceRes mapSpotToDto(Spot spot) { + private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { - final long memberId = SecurityUtil.getCurrentMemberId(); + Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 현재 로그인 유저의 좋아요 여부 @@ -101,15 +106,16 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { .placeType(placeType) .memberId(spot.getMember().getId()) .name(spot.getName()) - .latitude(spot.getLatitude()) - .longitude(spot.getLongitude()) + //위도, 경도 double로 변경 필요 + //.latitude(spot.getLatitude()) + //.longitude(spot.getLongitude()) //.image(spot.getImage()) .stars(spot.getStars()) - // .guestbookCount(guestRepository.countBySpotId(spot.getID())) + //.guestbookCount(guestRepository.countBySpotId(spot.getID())) .isFavorited(spotLiked) .createdAt(spot.getCreatedAt()) .build(); - }*/ + } // 전체 조회 @Transactional @@ -241,4 +247,67 @@ public ResponseEntity getAllPlacesLatest(HttpServletRequest request, Pageable return ResponseEntity.ok(apiResponse); } + + // 장소 검색 + public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq searchPlaceReq, Pageable pageable) { + + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + List allPlaces = getAllPlaceResList(request, pageable); + + // 검색어 포함 + 동일한 동ID 가진 장소 필터링 + List searchResult = new ArrayList<>(); + for (GetAllPlaceRes place : allPlaces) { + if (place.getName().contains(searchPlaceReq.getKeyword()) || + (place.getDongAreaId() != null && place.getDongAreaId().equals(searchPlaceReq.getDongAreaId()))) { + searchResult.add(place); + } + } + + // 이름에 검색어가 포함된 장소들을 우선적으로 정렬 + Collections.sort(searchResult, Comparator.comparing(place -> { + if (place.getName().contains(searchPlaceReq.getKeyword())) { + return 0; + } else { + return 1; + } + })); + + // 페이징 + int page = pageable.getPageNumber(); + int size = pageable.getPageSize(); + List paginatedResult = searchResult.stream() + .skip(page * size) + .limit(size) + .collect(Collectors.toList()); + + // 반환할 데이터가 없으면 빈 목록 반환 + if (paginatedResult.isEmpty()) { + return ResponseEntity.ok().body(Collections.emptyList()); + } + + List searchPlaceRes = paginatedResult.stream() + .map(place -> SearchPlaceRes.builder() + .placeId(place.getPlaceId()) + .placeType(place.getPlaceType()) + .dongAreaId(place.getDongAreaId()) + .memberId(place.getMemberId()) + .name(place.getName()) + .latitude(place.getLatitude()) + .longitude(place.getLongitude()) + .image(place.getImage()) + .stars(place.getStars()) + .guestbookCount(place.getGuestbookCount()) + .likesCount(place.getLikesCount()) + .isFavorited(place.getIsFavorited()) + .build()) + .collect(Collectors.toList()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(searchPlaceRes) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java b/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java new file mode 100644 index 00000000..62a6fa36 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.place.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class SearchPlaceReq { + + @Schema(description = "검색어") + private String keyword; + + @Schema(description = "지역(동) ID") + private Long dongAreaId; +} diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index c21c3d01..4f45290f 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -16,6 +16,9 @@ public class GetAllPlaceRes { @Schema(description = "매장 또는 산책스팟") private PlaceType placeType; + @Schema(description = "동(지역) ID") + private Long dongAreaId; + @Schema(description = "등록유저 ID") private Long memberId; @@ -53,11 +56,12 @@ public class GetAllPlaceRes { private Double distance; @Builder - public GetAllPlaceRes(Long placeId, PlaceType placeType, Long memberId, String name, Double latitude, Double longitude, + public GetAllPlaceRes(Long placeId, PlaceType placeType, Long dongAreaId, Long memberId, String name, Double latitude, Double longitude, String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, LocalDateTime createdAt, Integer recommendationScore, Double distance) { this.placeId = placeId; this.placeType = placeType; + this.dongAreaId = dongAreaId; this.memberId = memberId; this.name = name; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java new file mode 100644 index 00000000..1fbd9be5 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java @@ -0,0 +1,63 @@ +package com.ttubeog.domain.place.dto.response; + +import com.ttubeog.domain.place.domain.PlaceType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +public class SearchPlaceRes { + + @Schema(description = "장소 ID") + private Long placeId; + + @Schema(description = "매장 또는 산책스팟") + private PlaceType placeType; + + @Schema(description = "동(지역) ID") + private Long dongAreaId; + + @Schema(description = "등록유저 ID") + private Long memberId; + + @Schema(description = "장소 이름") + private String name; + + @Schema(description = "위도") + private Double latitude; + + @Schema(description = "경도") + private Double longitude; + + @Schema(description = "대표 이미지") + private String image; + + @Schema(description = "별점") + private Float stars; + + @Schema(description = "방명록 수") + private Integer guestbookCount; + + @Schema(description = "좋아요 수") + private Integer likesCount; + + @Schema(description = "좋아요 여부") + private Boolean isFavorited; + + @Builder + public SearchPlaceRes(Long placeId, PlaceType placeType, Long dongAreaId, Long memberId, String name, Double latitude, Double longitude, + String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { + this.placeId = placeId; + this.placeType = placeType; + this.dongAreaId = dongAreaId; + this.memberId = memberId; + this.name = name; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.stars = stars; + this.guestbookCount = guestbookCount; + this.likesCount = likesCount; + this.isFavorited = isFavorited; + } +} diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index 8990c0ca..b4f4dc4c 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -2,7 +2,9 @@ import com.ttubeog.domain.place.application.PlaceService; import com.ttubeog.domain.place.dto.request.GetNearbyPlaceReq; +import com.ttubeog.domain.place.dto.request.SearchPlaceReq; import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; +import com.ttubeog.domain.place.dto.response.SearchPlaceRes; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -36,7 +38,8 @@ public class PlaceController { public ResponseEntity getAllPlaces( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "10") int size + ) { Pageable pageable = PageRequest.of(page, size); return placeService.getAllPlaces(request, pageable); } @@ -51,7 +54,8 @@ public ResponseEntity getAllPlaces( public ResponseEntity getAllPlacesRecommended( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "10") int size + ) { Pageable pageable = PageRequest.of(page, size); return placeService.getAllPlacesRecommended(request, pageable); } @@ -65,7 +69,7 @@ public ResponseEntity getAllPlacesRecommended( @GetMapping("/nearby") public ResponseEntity getAllPlacesNearby( HttpServletRequest request, - @Valid @RequestBody GetNearbyPlaceReq getNearbyPlaceReq, + @Valid GetNearbyPlaceReq getNearbyPlaceReq, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { @@ -83,8 +87,26 @@ public ResponseEntity getAllPlacesNearby( public ResponseEntity getAllPlacesLatest( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "10") int size + ) { Pageable pageable = PageRequest.of(page, size); return placeService.getAllPlacesLatest(request, pageable); } + + // 장소 검색 + @Operation(summary = "장소 검색", description = "키워드를 입력받아 장소를 검색합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "장소 검색 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = SearchPlaceRes.class))}), + @ApiResponse(responseCode = "400", description = "장소 검색 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @GetMapping("/search") + public ResponseEntity searchPlace( + HttpServletRequest request, + @Valid SearchPlaceReq searchPlaceReq, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size + ) { + Pageable pageable = PageRequest.of(page, size); + return placeService.searchPlaces(request, searchPlaceReq, pageable); + } } From dc932d669ecba79d41f5d56009eb5153066f4ad5 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 03:00:27 +0900 Subject: [PATCH 259/356] =?UTF-8?q?[Refactor]=20guestbook=20=EB=A6=AC?= =?UTF-8?q?=ED=8E=99=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/road/application/RoadService.java | 160 ++++++++++++++++++ .../com/ttubeog/domain/road/domain/Road.java | 50 ++++++ .../ttubeog/domain/road/domain/RoadType.java | 11 ++ .../dto/request/CreateRoadRequestDto.java | 23 +++ .../road/dto/response/RoadResponseDto.java | 33 ++++ .../exception/InvalidRoadIdException.java | 12 ++ .../exception/InvalidRoadTypeException.java | 12 ++ .../NullRoadCoordinateException.java | 12 ++ .../road/presentation/RoadController.java | 145 +++++++++++++++- .../application/RoadCoordinateService.java | 4 + .../roadcoordinate/domain/RoadCoordinate.java | 42 +++++ .../repository/RoadCoordinateRepository.java | 15 ++ .../CreateRoadCoordinateRequestDto.java | 9 + .../response/RoadResponseCoordinateDto.java | 8 + 14 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/road/domain/RoadType.java create mode 100644 src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java create mode 100644 src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java create mode 100644 src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java create mode 100644 src/main/java/com/ttubeog/domain/road/exception/NullRoadCoordinateException.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 9b8d51b1..369f242b 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -1,11 +1,171 @@ package com.ttubeog.domain.road.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.road.domain.Road; +import com.ttubeog.domain.road.domain.RoadType; +import com.ttubeog.domain.road.domain.repository.RoadRepository; +import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.domain.road.dto.response.RoadResponseDto; +import com.ttubeog.domain.road.exception.InvalidRoadIdException; +import com.ttubeog.domain.road.exception.InvalidRoadTypeException; +import com.ttubeog.domain.road.exception.NullRoadCoordinateException; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.roadcoordinate.domain.repository.RoadCoordinateRepository; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.InvalidStoreIdException; +import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) public class RoadService { + + private final JwtTokenProvider jwtTokenProvider; + + private final RoadRepository roadRepository; + private final RoadCoordinateRepository roadCoordinateRepository; + private final MemberRepository memberRepository; + private final SpotRepository spotRepository; + private final StoreRepository storeRepository; + + @Transactional + public ResponseEntity createRoad(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Road road; + + List roadCoordinateList = new ArrayList<>(); + List> createRoadRequestDtoRoadCoordinate = createRoadRequestDto.getRoadCoordinate(); + for (List roadCoordinateDto : createRoadRequestDtoRoadCoordinate) { + RoadCoordinate roadCoordinate = RoadCoordinate.builder() + .latitude(roadCoordinateDto.get(0)) + .longitude(roadCoordinateDto.get(1)) + .build(); + roadCoordinateList.add(roadCoordinate); + } + + if (roadCoordinateList.isEmpty()) { + throw new NullRoadCoordinateException(); + } + + + if (createRoadRequestDto.getRoadType().equals(RoadType.SPOT)) { + Spot spot = spotRepository.findById(createRoadRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); + road = Road.builder() + .roadType(RoadType.SPOT) + .spot(spot) + .member(member) + .name(createRoadRequestDto.getName()) + .roadCoordinateList(roadCoordinateList) + .time(createRoadRequestDto.getTime()) + .build(); + roadRepository.save(road); + } else if (createRoadRequestDto.getRoadType().equals(RoadType.STORE)) { + Store store = storeRepository.findById(createRoadRequestDto.getStoreId()).orElseThrow(InvalidStoreIdException::new); + road = Road.builder() + .roadType(RoadType.STORE) + .store(store) + .member(member) + .name(createRoadRequestDto.getName()) + .roadCoordinateList(roadCoordinateList) + .time(createRoadRequestDto.getTime()) + .build(); + roadRepository.save(road); + } else { + throw new InvalidRoadTypeException(); + } + + for (RoadCoordinate roadCoordinate: roadCoordinateList) { + roadCoordinate.updateRoad(road); + } + + roadCoordinateRepository.saveAll(roadCoordinateList); + + RoadResponseDto roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(road.getRoadType()) + .spot(road.getSpot()) + .store(road.getStore()) + .member(road.getMember()) + .name(road.getName()) + .roadCoordinate(road.getRoadCoordinateList()) + .time(road.getTime()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(roadResponseDto) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + public ResponseEntity findById(HttpServletRequest request, Long roadId) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Road road = roadRepository.findById(roadId).orElseThrow(InvalidRoadIdException::new); + + RoadResponseDto roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(road.getRoadType()) + .spot(road.getSpot()) + .store(road.getStore()) + .member(road.getMember()) + .name(road.getName()) + .roadCoordinate(road.getRoadCoordinateList()) + .time(road.getTime()) + .build(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(roadResponseDto) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + @Transactional + public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Road road = roadRepository.findById(roadId).orElseThrow(InvalidRoadIdException::new); + + List roadCoordinateList = roadCoordinateRepository.findByRoad(road); + + roadRepository.delete(road); + + roadCoordinateRepository.deleteAll(roadCoordinateList); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("산책로를 삭제햇습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index efc2bdcd..408e86c9 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -5,11 +5,61 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity +@Getter +@Builder +@Table(name = "road") public class Road extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "road_type", nullable = false) + private RoadType roadType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "spot_id") + private Spot spot; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @Column(name = "name", nullable = false) + private String name; + + @OneToMany(mappedBy = "road", cascade = CascadeType.ALL) + private List roadCoordinateList; + + @Column(name = "time", nullable = false) + private String time; + + public Road(Long id, RoadType roadType, Spot spot, Store store, Member member, String name, List roadCoordinateList, String time) { + this.id = id; + this.roadType = roadType; + this.spot = spot; + this.store = store; + this.member = member; + this.name = name; + this.roadCoordinateList = roadCoordinateList; + this.time = time; + } } diff --git a/src/main/java/com/ttubeog/domain/road/domain/RoadType.java b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java new file mode 100644 index 00000000..c7d9da49 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java @@ -0,0 +1,11 @@ +package com.ttubeog.domain.road.domain; + +import lombok.Getter; + +@Getter +public enum RoadType { + + SPOT, + STORE; + +} diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java new file mode 100644 index 00000000..ea07392e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -0,0 +1,23 @@ +package com.ttubeog.domain.road.dto.request; + +import com.ttubeog.domain.road.domain.RoadType; +import lombok.Data; + +import java.util.List; + +@Data +public class CreateRoadRequestDto { + + private RoadType roadType; + + private Long spotId; + + private Long storeId; + + private String name; + + private List> roadCoordinate; + + private String time; + +} diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java new file mode 100644 index 00000000..36b3683b --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -0,0 +1,33 @@ +package com.ttubeog.domain.road.dto.response; + +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.road.domain.RoadType; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +public class RoadResponseDto { + + private Long id; + + private RoadType roadType; + + private Spot spot; + + private Store store; + + private Member member; + + private String name; + + private List roadCoordinate; + + private String time; + +} diff --git a/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java new file mode 100644 index 00000000..2c45f989 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.road.exception; + +public class InvalidRoadIdException extends RuntimeException { + + public InvalidRoadIdException() { + super("올바르지 않은 산책로 ID 입니다."); + } + + public InvalidRoadIdException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java new file mode 100644 index 00000000..c22430fb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.road.exception; + +public class InvalidRoadTypeException extends RuntimeException { + + public InvalidRoadTypeException() { + super("유효하지 않은 산책로 타입입니다."); + } + + public InvalidRoadTypeException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/road/exception/NullRoadCoordinateException.java b/src/main/java/com/ttubeog/domain/road/exception/NullRoadCoordinateException.java new file mode 100644 index 00000000..c284bd64 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/NullRoadCoordinateException.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.road.exception; + +public class NullRoadCoordinateException extends NullPointerException { + + public NullRoadCoordinateException() { + super("빈 경로 배열입니다."); + } + + public NullRoadCoordinateException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 50380913..94c37d2a 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -1,7 +1,150 @@ package com.ttubeog.domain.road.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.road.application.RoadService; +import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.domain.spot.dto.response.SpotResponseDto; +import com.ttubeog.global.config.security.token.CurrentUser; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +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.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Road", description = "Road API(산책로 API)") +@RequiredArgsConstructor +@RequestMapping("api/v1/road") @RestController public class RoadController { + + private final RoadService roadService; + + /** + * 산책 스팟 생성 API + * @param request 유저 검증 + * @param createRoadRequestDto 산책로 생성 DTO + * @return ResponseEntity -> RoadResponseDto + * @throws JsonProcessingException json processing 에러 + */ + @Operation(summary = "산책로 생성", + description = "산책로를 생성합니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) + @PostMapping + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createRoad( + @CurrentUser HttpServletRequest request, + @RequestBody CreateRoadRequestDto createRoadRequestDto + ) throws JsonProcessingException { + return roadService.createRoad(request, createRoadRequestDto); + } + + /** + * 산책로 조회 API + * @param request 유저 검증 + * @param roadId 산책로 Id + * @return ResponseEntity -> RoadResponseDto + * @throws JsonProcessingException json processing 에러 + */ + @Operation(summary = "산책로 조회", + description = "산책로를 Id 값을 통해 조회합니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) + @GetMapping("/{roadId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findRoadById( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "roadId") Long roadId + ) throws JsonProcessingException { + return roadService.findById(request, roadId); + } + + + /** + * 산책로 삭제 API + * @param request 유저 검증 + * @param roadId 산책로 Id + * @return ResponseEntity -> RoadResponseDto + * @throws JsonProcessingException json processing 에러 + */ + @Operation(summary = "산책로 삭제", + description = "산책로를 삭제합니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) + @DeleteMapping("/{roadId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteRoad( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "roadId") Long roadId + ) throws JsonProcessingException { + return roadService.deleteRoad(request, roadId); + } + } diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java b/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java new file mode 100644 index 00000000..0619b8cb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java @@ -0,0 +1,4 @@ +package com.ttubeog.domain.roadcoordinate.application; + +public class RoadCoordinateService { +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java new file mode 100644 index 00000000..0e8a3202 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java @@ -0,0 +1,42 @@ +package com.ttubeog.domain.roadcoordinate.domain; + +import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.road.domain.Road; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Getter +@Builder +@Table(name = "road_coordinate") +public class RoadCoordinate extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "road_id") + private Road road; + + @Column(name = "latitude", nullable = false) + private Float latitude; + + @Column(name = "longitude", nullable = false) + private Float longitude; + + public RoadCoordinate(Long id, Road road, Float latitude, Float longitude) { + this.id = id; + this.road = road; + this.latitude = latitude; + this.longitude = longitude; + } + + public void updateRoad(Road road) { + this.road = road; + } +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java new file mode 100644 index 00000000..73bb56ae --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java @@ -0,0 +1,15 @@ +package com.ttubeog.domain.roadcoordinate.domain.repository; + +import com.ttubeog.domain.road.domain.Road; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface RoadCoordinateRepository extends JpaRepository { + + List findByRoad(Road road); + +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java new file mode 100644 index 00000000..aefc3378 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.roadcoordinate.dto.request; + +import lombok.Data; + +@Data +public class CreateRoadCoordinateRequestDto { + + +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java new file mode 100644 index 00000000..04a99e42 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java @@ -0,0 +1,8 @@ +package com.ttubeog.domain.roadcoordinate.dto.response; + + +import lombok.Data; + +@Data +public class RoadResponseCoordinateDto { +} From 04d438873e5a5d0cfb6bb71ff8cf0fd7d18479d7 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 03:17:28 +0900 Subject: [PATCH 260/356] =?UTF-8?q?[Feat]=20=EB=8C=80=ED=91=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 72bec486..2edb71a0 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -77,6 +78,16 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { Boolean storeLiked = likesRepository.existsByMemberIdAndStoreId(memberId, store.getId()); PlaceType placeType = new PlaceType(true, false); + // 가장 인덱스가 작은 이미지 선택 + List storeImages = imageRepository.findByStoreId(store.getId()); + String representativeImageUrl = null; + if (!storeImages.isEmpty()) { + Image representativeImage = storeImages.stream() + .min(Comparator.comparingLong(Image::getId)) + .orElseThrow(); + representativeImageUrl = representativeImage.getImage(); + } + return GetAllPlaceRes.builder() .placeId(store.getId()) .placeType(placeType) @@ -84,6 +95,7 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { .name(store.getName()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) + .image(representativeImageUrl) // .image(store.getImage()) .stars(store.getStars()) // .guestbookCount(guestRepository.countByStoreId(store.getID())) @@ -101,6 +113,16 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { Boolean spotLiked = likesRepository.existsByMemberIdAndSpotId(memberId, spot.getId()); PlaceType placeType = new PlaceType(false, true); + // 가장 인덱스가 작은 이미지 선택 + List spotImages = imageRepository.findBySpotId(spot.getId()); + String representativeImageUrl = null; + if (!spotImages.isEmpty()) { + Image representativeImage = spotImages.stream() + .min(Comparator.comparingLong(Image::getId)) + .orElseThrow(); + representativeImageUrl = representativeImage.getImage(); + } + return GetAllPlaceRes.builder() .placeId(spot.getId()) .placeType(placeType) @@ -109,7 +131,7 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { //위도, 경도 double로 변경 필요 //.latitude(spot.getLatitude()) //.longitude(spot.getLongitude()) - //.image(spot.getImage()) + .image(representativeImageUrl) .stars(spot.getStars()) //.guestbookCount(guestRepository.countBySpotId(spot.getID())) .isFavorited(spotLiked) From 92084d8402352a8a74c7bba9626f213722c695ea Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 04:09:36 +0900 Subject: [PATCH 261/356] =?UTF-8?q?[Feat]=20storeId=EB=A1=9C=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=A1=B0=ED=9A=8C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../benefit/application/BenefitService.java | 8 +-- .../domain/game/application/GameService.java | 61 +++++++++++++++---- .../domain/repository/GameRepository.java | 9 --- ...eBenefitResDto.java => BenefitResDto.java} | 4 +- .../game/dto/response/CreateRouletteRes.java | 4 +- .../game/dto/response/UpdateRouletteRes.java | 5 +- .../game/presentation/GameController.java | 4 +- .../store/presentation/StoreController.java | 19 ++++++ 8 files changed, 77 insertions(+), 37 deletions(-) rename src/main/java/com/ttubeog/domain/game/dto/response/{RouletteBenefitResDto.java => BenefitResDto.java} (83%) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index a88e097a..74f39940 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.benefit.application; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; @@ -12,15 +11,11 @@ import com.ttubeog.domain.benefit.exception.InvalidMemberBenefitException; import com.ttubeog.domain.benefit.exception.NonExistentBenefitException; import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; -import com.ttubeog.domain.game.domain.repository.GameRepository; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; -import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -40,9 +35,8 @@ public class BenefitService { private final MemberRepository memberRepository; private final BenefitRepository benefitRepository; - private final StoreRepository storeRepository; private final MemberBenefitRepository memberBenefitRepository; - private final GameRepository gameRepository; + private final StoreRepository storeRepository; private final JwtTokenProvider jwtTokenProvider; //게임 성공 후 혜택 저장 diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index cb2c4251..98158af8 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.game.application; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.MemberBenefit; @@ -20,7 +19,6 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; @@ -30,10 +28,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.HashSet; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; @RequiredArgsConstructor @@ -196,8 +192,8 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet .build(); rouletteRepository.save(rouletteGame); - List benefitResDtoList = benefitList.stream() - .map(benefit -> RouletteBenefitResDto.builder() + List benefitResDtoList = benefitList.stream() + .map(benefit -> BenefitResDto.builder() .benefitId(benefit.getId()) .content(benefit.getContent()) .type(benefit.getType()) @@ -321,8 +317,8 @@ public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRoulet rouletteGame.updateRoulette(updateRouletteReq.getOptions()); - List benefitResDtoList = newBenefitList.stream() - .map(benefit -> RouletteBenefitResDto.builder() + List benefitResDtoList = newBenefitList.stream() + .map(benefit -> BenefitResDto.builder() .benefitId(benefit.getId()) .content(benefit.getContent()) .type(benefit.getType()) @@ -407,8 +403,8 @@ public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) th Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(game); - List benefitResDtoList = benefitList.stream() - .map(benefit -> RouletteBenefitResDto.builder() + List benefitResDtoList = benefitList.stream() + .map(benefit -> BenefitResDto.builder() .benefitId(benefit.getId()) .content(benefit.getContent()) .type(benefit.getType()) @@ -423,4 +419,47 @@ public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) th return ResponseEntity.ok(apiResponse); } + //매장ID로 게임 조회 + public ResponseEntity findByStore(HttpServletRequest request, Long storeId) throws JsonProcessingException { + Long memberId = jwtTokenProvider.getMemberId(request); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); + List benefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); + + List gameList = benefitList.stream() + .map(Benefit::getGame) + .distinct() // 중복 제거 + .collect(Collectors.toList()); + + // 변환된 FindGameRes 리스트를 저장할 리스트 + List findGameResList = new ArrayList<>(); + + for (Game game : gameList) { + FindGameRes.FindGameResBuilder builder = FindGameRes.builder() + .gameId(game.getId()) + .type(game.getType()); + + if (game.getType() == GameType.BASKETBALL) { + builder.timeLimit(game.getBasketballGame().getTimeLimit()) + .ballCount(game.getBasketballGame().getBallCount()) + .successCount(game.getBasketballGame().getSuccessCount()); + } else if (game.getType() == GameType.GIFT) { + builder.timeLimit(game.getGiftGame().getTimeLimit()) + .giftCount(game.getGiftGame().getGiftCount()); + } else if (game.getType() == GameType.ROULETTE) { + Hibernate.initialize(game.getRouletteGame().getOptions()); // 명시적 초기화 + builder.options(game.getRouletteGame().getOptions()); + } + + FindGameRes findGameRes = builder.build(); + findGameResList.add(findGameRes); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(findGameResList) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java index 2ddf189d..cda63ee9 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java +++ b/src/main/java/com/ttubeog/domain/game/domain/repository/GameRepository.java @@ -1,18 +1,9 @@ package com.ttubeog.domain.game.domain.repository; -import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.game.domain.Game; -import com.ttubeog.domain.game.domain.GameType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; -import java.util.Optional; - @Repository public interface GameRepository extends JpaRepository { - -// Boolean existsByBenefitAndType(Benefit benefit, GameType type); - -// Optional findByBenefit(Benefit benefit); } diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java b/src/main/java/com/ttubeog/domain/game/dto/response/BenefitResDto.java similarity index 83% rename from src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java rename to src/main/java/com/ttubeog/domain/game/dto/response/BenefitResDto.java index 1fb0fd78..e1781407 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/RouletteBenefitResDto.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/BenefitResDto.java @@ -6,7 +6,7 @@ import lombok.Data; @Data -public class RouletteBenefitResDto { +public class BenefitResDto { @Schema(description = "혜택 Id", example = "1") @@ -21,7 +21,7 @@ public class RouletteBenefitResDto { private BenefitType type; @Builder - public RouletteBenefitResDto(Long benefitId, String content, BenefitType type) { + public BenefitResDto(Long benefitId, String content, BenefitType type) { this.benefitId = benefitId; this.content = content; this.type = type; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java index 24e11083..e55a8571 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateRouletteRes.java @@ -18,10 +18,10 @@ public class CreateRouletteRes { @Schema(description = "매장ID", example = "1") private Long storeId; - private List benefits; + private List benefits; @Builder - public CreateRouletteRes(Long gameId, Long storeId, List options, List benefits) { + public CreateRouletteRes(Long gameId, Long storeId, List options, List benefits) { this.gameId = gameId; this.storeId = storeId; this.options = options; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java index d17e2148..636b48da 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateRouletteRes.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.game.dto.response; -import com.ttubeog.domain.benefit.domain.BenefitType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -19,10 +18,10 @@ public class UpdateRouletteRes { @Schema(description = "옵션 내용", example = "[\"5% 할인\",\"아메리카노 증정\"]") private List options; - private List benefits; + private List benefits; @Builder - public UpdateRouletteRes(Long gameId, Long storeId, List options, List benefits) { + public UpdateRouletteRes(Long gameId, Long storeId, List options, List benefits) { this.gameId = gameId; this.storeId = storeId; this.options = options; diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index db4d4f36..f947eb7e 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -4,8 +4,6 @@ import com.ttubeog.domain.game.application.GameService; import com.ttubeog.domain.game.dto.request.*; import com.ttubeog.domain.game.dto.response.*; -import com.ttubeog.global.config.security.token.CurrentUser; -import com.ttubeog.global.config.security.token.UserPrincipal; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -143,7 +141,7 @@ public ResponseEntity findGame( //게임 조회 @Operation(summary = "혜택 조회", description = "게임Id로 혜택 정보를 조회합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = RouletteBenefitResDto.class) ) } ), + @ApiResponse(responseCode = "200", description = "조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = BenefitResDto.class) ) } ), @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @GetMapping("/{gameId}/benefit") diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 58589c53..db9e80ea 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,5 +1,9 @@ package com.ttubeog.domain.store.presentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.application.BenefitService; +import com.ttubeog.domain.game.application.GameService; +import com.ttubeog.domain.game.dto.response.FindGameRes; import com.ttubeog.domain.likes.application.LikesService; import com.ttubeog.domain.store.application.StoreService; import com.ttubeog.domain.store.dto.request.RegisterStoreReq; @@ -29,6 +33,7 @@ public class StoreController { private final StoreService storeService; private final LikesService likesService; + private final GameService gameService; // 매장 등록 @@ -100,4 +105,18 @@ public ResponseEntity likesStore( ) { return likesService.likesStore(request, storeId); } + + //StoreId로 매장 조회 + @Operation(summary = "매장ID로 게임 조회", description = "매장에 해당하는 모든 게임을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "게임 조회 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class))}), + @ApiResponse(responseCode = "400", description = "게임 조회 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping("/{storeId}/game") + public ResponseEntity findBenefitByStore( + HttpServletRequest request, + @PathVariable Long storeId + ) throws JsonProcessingException { + return gameService.findByStore(request, storeId); + } } From 9d629933b964d8cd8732813cb54b2526b0f9d439 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 04:17:14 +0900 Subject: [PATCH 262/356] =?UTF-8?q?[Chore]=20TimeLimit=20=EC=9E=90?= =?UTF-8?q?=EB=A3=8C=ED=98=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/game/domain/BasketballGame.java | 8 +++----- .../java/com/ttubeog/domain/game/domain/GiftGame.java | 8 +++----- .../domain/game/dto/request/CreateBasketballReq.java | 6 ++---- .../ttubeog/domain/game/dto/request/CreateGiftReq.java | 6 ++---- .../domain/game/dto/request/UpdateBasketballReq.java | 6 ++---- .../ttubeog/domain/game/dto/request/UpdateGiftReq.java | 6 ++---- .../domain/game/dto/response/CreateBasketballRes.java | 8 +++----- .../ttubeog/domain/game/dto/response/CreateGiftRes.java | 8 +++----- .../com/ttubeog/domain/game/dto/response/FindGameRes.java | 8 +++----- .../domain/game/dto/response/UpdateBasketballRes.java | 8 +++----- .../ttubeog/domain/game/dto/response/UpdateGiftRes.java | 8 +++----- 11 files changed, 29 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index ddbe897f..a869483c 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -7,8 +7,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalTime; - @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -25,7 +23,7 @@ public class BasketballGame extends BaseEntity { private Game game; @Column(name = "time_limit") - private LocalTime timeLimit; + private Integer timeLimit; @Column(name = "ball_count") private Integer ballCount; @@ -34,14 +32,14 @@ public class BasketballGame extends BaseEntity { private Integer successCount; @Builder - public BasketballGame(Game game, LocalTime timeLimit, Integer ballCount, Integer successCount) { + public BasketballGame(Game game, Integer timeLimit, Integer ballCount, Integer successCount) { this.game = game; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; } - public void updateTimeLimit(LocalTime timeLimit) { + public void updateTimeLimit(Integer timeLimit) { this.timeLimit = timeLimit; } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index 13427268..977b7512 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -7,8 +7,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalTime; - @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -25,19 +23,19 @@ public class GiftGame extends BaseEntity { private Game game; @Column(name = "time_limit") - private LocalTime timeLimit; + private Integer timeLimit; @Column(name = "gift_count") private Integer giftCount; @Builder - public GiftGame(Game game, LocalTime timeLimit, Integer giftCount) { + public GiftGame(Game game, int timeLimit, Integer giftCount) { this.game = game; this.timeLimit = timeLimit; this.giftCount = giftCount; } - public void updateTimeLimit(LocalTime timeLimit) { + public void updateTimeLimit(Integer timeLimit) { this.timeLimit = timeLimit; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java index 578c6d9e..36db6e10 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.time.LocalTime; - @Data @Schema(description = "CreateBasketballGameRequest") public class CreateBasketballReq { @@ -13,8 +11,8 @@ public class CreateBasketballReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java index 89e15d41..5c0f48f3 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.time.LocalTime; - @Data @Schema(description = "CreateGiftGameRequest") public class CreateGiftReq { @@ -13,8 +11,8 @@ public class CreateGiftReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java index 272a1ed9..021f9750 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.time.LocalTime; - @Data @Schema(description = "UpdateBasketballGameRequest") public class UpdateBasketballReq { @@ -16,8 +14,8 @@ public class UpdateBasketballReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java index 1287f955..fe2665e4 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.time.LocalTime; - @Data @Schema(description = "UpdateGiftGameRequest") public class UpdateGiftReq { @@ -16,8 +14,8 @@ public class UpdateGiftReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java index 312a2d50..821dae2c 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java @@ -5,8 +5,6 @@ import lombok.Builder; import lombok.Data; -import java.time.LocalTime; - @Data public class CreateBasketballRes { @@ -19,8 +17,8 @@ public class CreateBasketballRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; @@ -35,7 +33,7 @@ public class CreateBasketballRes { private BenefitType benefitType; @Builder - public CreateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public CreateBasketballRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java index 0267062d..d6065024 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -5,8 +5,6 @@ import lombok.Builder; import lombok.Data; -import java.time.LocalTime; - @Data public class CreateGiftRes { @@ -19,8 +17,8 @@ public class CreateGiftRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -32,7 +30,7 @@ public class CreateGiftRes { private BenefitType benefitType; @Builder - public CreateGiftRes(Long benefitId, Long gameId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public CreateGiftRes(Long benefitId, Long gameId, Long storeId, Integer timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.benefitId = benefitId; this.gameId = gameId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 883fb67c..261fb002 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; - -import java.time.LocalTime; import java.util.List; @Data @@ -17,8 +15,8 @@ public class FindGameRes { @Schema(description = "종류", example = "roulette") private GameType type; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -33,7 +31,7 @@ public class FindGameRes { private List options; @Builder - public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { + public FindGameRes(Long gameId, GameType type, Integer timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { this.gameId = gameId; this.type = type; this.timeLimit = timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java index b17a08bd..77310860 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java @@ -5,8 +5,6 @@ import lombok.Builder; import lombok.Data; -import java.time.LocalTime; - @Data public class UpdateBasketballRes { @@ -19,8 +17,8 @@ public class UpdateBasketballRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; @@ -35,7 +33,7 @@ public class UpdateBasketballRes { private BenefitType benefitType; @Builder - public UpdateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public UpdateBasketballRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java index 827e335b..6b0658db 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java @@ -5,8 +5,6 @@ import lombok.Builder; import lombok.Data; -import java.time.LocalTime; - @Data public class UpdateGiftRes { @@ -19,8 +17,8 @@ public class UpdateGiftRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "00:01:30") - private LocalTime timeLimit; + @Schema(description = "시간제한", example = "15") + private Integer timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -32,7 +30,7 @@ public class UpdateGiftRes { private BenefitType benefitType; @Builder - public UpdateGiftRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public UpdateGiftRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; From 0accc88ccf7ab7aabb4ce48db3cae30f18a43c33 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 04:22:19 +0900 Subject: [PATCH 263/356] =?UTF-8?q?[Feat]=20RoadController=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/road/application/RoadService.java | 22 +++++++ .../com/ttubeog/domain/road/domain/Road.java | 23 +++++++- .../dto/request/CreateRoadRequestDto.java | 20 +++++++ .../road/dto/response/RoadResponseDto.java | 24 ++++++++ .../road/presentation/RoadController.java | 58 ++++++++++++++++++- .../roadcoordinate/domain/RoadCoordinate.java | 38 ++++++++++++ .../repository/RoedCoordinateRepository.java | 9 +++ 7 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java create mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 9b8d51b1..693c0980 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.road.application; +import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,4 +11,23 @@ @Service @Transactional(readOnly = true) public class RoadService { + public ResponseEntity createGuestBook(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { + + return null; + } + + public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotId, Long pageNum) { + + return null; + } + + public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long storeId, Long pageNum) { + + return null; + } + + public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { + + return null; + } } diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index b289220d..28410805 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -2,11 +2,20 @@ import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; @Entity +@Getter +@Builder +@NoArgsConstructor public class Road extends BaseEntity { @Id @@ -28,9 +37,19 @@ public class Road extends BaseEntity { @Column(name = "name", nullable = false) private String name; - @Column(name = "road_file", nullable = false) - private String roadFile; + @OneToMany(mappedBy = "road", cascade = CascadeType.ALL) + private List roadCoordinateList; @Column(name = "time", nullable = false) private String time; + + public Road(Long id, Spot spot, Store store, Member member, String name, List roadCoordinateList, String time) { + this.id = id; + this.spot = spot; + this.store = store; + this.member = member; + this.name = name; + this.roadCoordinateList = roadCoordinateList; + this.time = time; + } } diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java index 04d23fa4..419c744c 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -1,4 +1,24 @@ package com.ttubeog.domain.road.dto.request; +import lombok.Data; +import lombok.Getter; + +import java.util.List; + +@Data +@Getter public class CreateRoadRequestDto { + + private Long spotId; + + private Long storeId; + + private Long memberId; + + private String name; + + private List> roadCoordinateList; + + private String time; + } diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java index 907f2d6c..d1822cce 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -1,4 +1,28 @@ package com.ttubeog.domain.road.dto.response; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; + +import java.util.List; + +@Data +@Getter +@Builder public class RoadResponseDto { + + private Long id; + + private Long spotId; + + private Long storeId; + + private Long memberId; + + private String name; + + private List> roadCoordinateList; + + private String time; + } diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 50380913..8d930b25 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -1,7 +1,63 @@ package com.ttubeog.domain.road.presentation; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; +import com.ttubeog.domain.road.application.RoadService; +import com.ttubeog.domain.road.domain.repository.RoadRepository; +import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.global.config.security.token.CurrentUser; +import io.swagger.v3.core.util.Json; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.*; +@Tag(name = "Road", description = "Road API(산책로 API)") +@RequiredArgsConstructor @RestController +@RequestMapping("api/v1/road") public class RoadController { + + private final RoadService roadService; + + @PostMapping + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createRoad( + @CurrentUser HttpServletRequest request, + @RequestBody CreateRoadRequestDto createRoadRequestDto + ) throws JsonProcessingException { + return roadService.createGuestBook(request, createRoadRequestDto); + } + + @GetMapping("/{spotId}&{pageNum}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findRoadBySpotId( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "spotId") Long spotId, + @RequestParam(name = "pageNum") Long pageNum + ) throws JsonProcessingException { + return roadService.findRoadBySpotId(request, spotId, pageNum); + } + + @GetMapping("/{storeId}&{pageNum}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findRoadByStoreId( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "storeId") Long storeId, + @RequestParam(name = "pageNum") Long pageNum + ) throws JsonProcessingException { + return roadService.findRoadByStoreId(request, storeId, pageNum); + } + + @DeleteMapping("/{roadId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteRoad( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "roadId") Long roadId + ) throws JsonProcessingException { + return roadService.deleteRoad(request, roadId); + } } diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java new file mode 100644 index 00000000..037c2201 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java @@ -0,0 +1,38 @@ +package com.ttubeog.domain.roadcoordinate.domain; + +import com.ttubeog.domain.common.BaseEntity; +import com.ttubeog.domain.road.domain.Road; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Tag(name = "road_coordinate") +@Entity +@Getter +@Builder +@NoArgsConstructor +public class RoadCoordinate extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "road_id") + private Road road; + + @Column(name = "latitude") + private Double latitude; + + @Column(name = "longitude") + private Double longitude; + + public RoadCoordinate(Long id, Road road, Double latitude, Double longitude) { + this.id = id; + this.road = road; + this.latitude = latitude; + this.longitude = longitude; + } +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java new file mode 100644 index 00000000..40524218 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java @@ -0,0 +1,9 @@ +package com.ttubeog.domain.roadcoordinate.domain.repository; + +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RoedCoordinateRepository extends JpaRepository { +} From 5e2bac9dc930a02f26b6e5b20ca5e220f7c2a42e Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 04:23:01 +0900 Subject: [PATCH 264/356] =?UTF-8?q?[Chore]=20unuse=20import=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/road/presentation/RoadController.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 8d930b25..982819f8 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -1,18 +1,14 @@ package com.ttubeog.domain.road.presentation; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; import com.ttubeog.domain.road.application.RoadService; -import com.ttubeog.domain.road.domain.repository.RoadRepository; import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; import com.ttubeog.global.config.security.token.CurrentUser; -import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.access.annotation.Secured; import org.springframework.web.bind.annotation.*; @Tag(name = "Road", description = "Road API(산책로 API)") From 3b65ec5dd5fe6cde67d885bd3484cdf015a2d918 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 04:44:44 +0900 Subject: [PATCH 265/356] =?UTF-8?q?[Feat]=20createGuestBook=20service=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 --- .../domain/road/application/RoadService.java | 61 +++++++++++++++++++ .../com/ttubeog/domain/road/domain/Road.java | 6 +- .../ttubeog/domain/road/domain/RoadType.java | 7 +++ .../domain/repository/RoadRepository.java | 5 ++ .../dto/request/CreateRoadRequestDto.java | 3 + .../road/dto/response/RoadResponseDto.java | 3 + .../exception/DuplicateRoadNameException.java | 12 ++++ .../exception/InvalidRoadTypeException.java | 12 ++++ .../roadcoordinate/domain/RoadCoordinate.java | 4 ++ 9 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ttubeog/domain/road/domain/RoadType.java create mode 100644 src/main/java/com/ttubeog/domain/road/exception/DuplicateRoadNameException.java create mode 100644 src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 693c0980..93871e74 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -1,18 +1,79 @@ package com.ttubeog.domain.road.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.road.domain.Road; +import com.ttubeog.domain.road.domain.RoadType; +import com.ttubeog.domain.road.domain.repository.RoadRepository; import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.domain.road.exception.DuplicateRoadNameException; +import com.ttubeog.domain.road.exception.InvalidRoadTypeException; +import com.ttubeog.domain.road.presentation.RoadController; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; +import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) public class RoadService { + + private final RoadRepository roadRepository; + private final SpotRepository spotRepository; + private final StoreRepository storeRepository; + private final MemberRepository memberRepository; + + private final JwtTokenProvider jwtTokenProvider; + public ResponseEntity createGuestBook(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Road road; + Spot spot; + Store store; + + List roadCoordinateList = new ArrayList<>(); + List> roadCoordinateDoubleList = createRoadRequestDto.getRoadCoordinateList(); + for (List roadCoordinateDouble : roadCoordinateDoubleList) { + RoadCoordinate roadCoordinate = RoadCoordinate.builder() + .latitude(roadCoordinateDouble.get(0)) + .longitude(roadCoordinateDouble.get(1)) + .build(); + roadCoordinateList.add(roadCoordinate); + } + + if (createRoadRequestDto.getRoadType().equals(RoadType.SPOT)) { + + spot = spotRepository.findById(createRoadRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); + + roadRepository.findBySpotAndName(spot, createRoadRequestDto.getName()).orElseThrow(DuplicateRoadNameException::new); + + road = Road.builder().build(); + + } else if (createRoadRequestDto.getRoadType().equals(RoadType.STORE)) { + + } else { + throw new InvalidRoadTypeException(); + } + + + return null; } diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index 28410805..00d88bd7 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -22,6 +22,9 @@ public class Road extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "road_type", nullable = false) + private RoadType roadType; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "spot_id") private Spot spot; @@ -43,8 +46,9 @@ public class Road extends BaseEntity { @Column(name = "time", nullable = false) private String time; - public Road(Long id, Spot spot, Store store, Member member, String name, List roadCoordinateList, String time) { + public Road(Long id, RoadType roadType, Spot spot, Store store, Member member, String name, List roadCoordinateList, String time) { this.id = id; + this.roadType = roadType; this.spot = spot; this.store = store; this.member = member; diff --git a/src/main/java/com/ttubeog/domain/road/domain/RoadType.java b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java new file mode 100644 index 00000000..84e89108 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.road.domain; + +public enum RoadType { + + SPOT, + STORE; +} diff --git a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java index 75ea6f08..adc18707 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java +++ b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java @@ -1,9 +1,14 @@ package com.ttubeog.domain.road.domain.repository; import com.ttubeog.domain.road.domain.Road; +import com.ttubeog.domain.spot.domain.Spot; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface RoadRepository extends JpaRepository { + + Optional findBySpotAndName(Spot spot, String name); } diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java index 419c744c..7e271c67 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.road.dto.request; +import com.ttubeog.domain.road.domain.RoadType; import lombok.Data; import lombok.Getter; @@ -9,6 +10,8 @@ @Getter public class CreateRoadRequestDto { + private RoadType roadType; + private Long spotId; private Long storeId; diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java index d1822cce..7e79b22a 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -1,5 +1,6 @@ package com.ttubeog.domain.road.dto.response; +import com.ttubeog.domain.road.domain.RoadType; import lombok.Builder; import lombok.Data; import lombok.Getter; @@ -13,6 +14,8 @@ public class RoadResponseDto { private Long id; + private RoadType roadType; + private Long spotId; private Long storeId; diff --git a/src/main/java/com/ttubeog/domain/road/exception/DuplicateRoadNameException.java b/src/main/java/com/ttubeog/domain/road/exception/DuplicateRoadNameException.java new file mode 100644 index 00000000..bdd27bb2 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/DuplicateRoadNameException.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.road.exception; + +public class DuplicateRoadNameException extends RuntimeException { + + public DuplicateRoadNameException() { + super("중복된 산책로 이름입니다."); + } + + public DuplicateRoadNameException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java new file mode 100644 index 00000000..c22430fb --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadTypeException.java @@ -0,0 +1,12 @@ +package com.ttubeog.domain.road.exception; + +public class InvalidRoadTypeException extends RuntimeException { + + public InvalidRoadTypeException() { + super("유효하지 않은 산책로 타입입니다."); + } + + public InvalidRoadTypeException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java index 037c2201..4402e4cb 100644 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java @@ -35,4 +35,8 @@ public RoadCoordinate(Long id, Road road, Double latitude, Double longitude) { this.latitude = latitude; this.longitude = longitude; } + + public void updateRoad(Road road) { + this.road = road; + } } From 2d9babb11b77fe660dba526b4dc632eb177c7ef0 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 13:31:18 +0900 Subject: [PATCH 266/356] =?UTF-8?q?[Feat]=20Game=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=8B=9C=20Benefit=EA=B9=8C=EC=A7=80=20=EA=B0=99=EC=9D=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 17 +++++++++++++++-- .../domain/game/dto/response/FindGameRes.java | 6 +++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 98158af8..1347cee1 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -368,10 +368,17 @@ public ResponseEntity findGame(HttpServletRequest request, Long gameId) throw Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); + List benefitList = benefitRepository.findAllByGame(game); + + List benefitResDtoList = benefitList.stream() + .filter(benefit -> benefit.getGame() != null && benefit.getGame().getId().equals(game.getId())) + .map(benefit -> new BenefitResDto(benefit.getId(), benefit.getContent(), benefit.getType())) + .collect(Collectors.toList()); FindGameRes.FindGameResBuilder builder = FindGameRes.builder() .gameId(game.getId()) - .type(game.getType()); + .type(game.getType()) + .benefits(benefitResDtoList); if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) @@ -431,7 +438,6 @@ public ResponseEntity findByStore(HttpServletRequest request, Long storeId) t .distinct() // 중복 제거 .collect(Collectors.toList()); - // 변환된 FindGameRes 리스트를 저장할 리스트 List findGameResList = new ArrayList<>(); for (Game game : gameList) { @@ -439,6 +445,13 @@ public ResponseEntity findByStore(HttpServletRequest request, Long storeId) t .gameId(game.getId()) .type(game.getType()); + List benefitResDtoList = benefitList.stream() + .filter(benefit -> benefit.getGame() != null && benefit.getGame().getId().equals(game.getId())) + .map(benefit -> new BenefitResDto(benefit.getId(), benefit.getContent(), benefit.getType())) + .collect(Collectors.toList()); + + builder.benefits(benefitResDtoList); + if (game.getType() == GameType.BASKETBALL) { builder.timeLimit(game.getBasketballGame().getTimeLimit()) .ballCount(game.getBasketballGame().getBallCount()) diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 261fb002..907d4fdc 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -30,8 +30,11 @@ public class FindGameRes { @Schema(description = "옵션 내용", example = "[\"꽝\",\"5% 할인\",\"아메리카노 증정\",\"꽝\"]") private List options; + @Schema(description = "해당 혜택") + private List benefits; + @Builder - public FindGameRes(Long gameId, GameType type, Integer timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options) { + public FindGameRes(Long gameId, GameType type, Integer timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options, List benefits) { this.gameId = gameId; this.type = type; this.timeLimit = timeLimit; @@ -39,5 +42,6 @@ public FindGameRes(Long gameId, GameType type, Integer timeLimit, Integer giftCo this.ballCount = ballCount; this.successCount = successCount; this.options = options; + this.benefits = benefits; } } From b780f46bd593fba7a6f5c36db89ada58933ade83 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 14:29:15 +0900 Subject: [PATCH 267/356] =?UTF-8?q?[Chore]=20=EA=B2=8C=EC=9E=84=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20sweagger=20=EC=84=A4=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/game/presentation/GameController.java | 4 ++-- .../ttubeog/domain/store/presentation/StoreController.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index f947eb7e..d0aa8ff5 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -124,8 +124,8 @@ public ResponseEntity deleteGame( return gameService.deleteGame(request, gameId); } - //게임 조회 - @Operation(summary = "게임 조회", description = "게임을 조회합니다.") + //게임, 혜택 조회 + @Operation(summary = "게임,혜택 조회", description = "게임과 해당 혜택을 조회합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class) ) } ), @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index db9e80ea..fe9eeb3c 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -106,8 +106,8 @@ public ResponseEntity likesStore( return likesService.likesStore(request, storeId); } - //StoreId로 매장 조회 - @Operation(summary = "매장ID로 게임 조회", description = "매장에 해당하는 모든 게임을 조회합니다.") + //StoreId로 매장, 혜택 조회 + @Operation(summary = "매장으로 게임, 혜택 조회", description = "매장ID에 해당하는 모든 게임과 해당 혜택을 조회합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "게임 조회 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class))}), @ApiResponse(responseCode = "400", description = "게임 조회 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) From ee6e338ffdfab73d1787414f93f8d0cc2735d443 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 14:44:01 +0900 Subject: [PATCH 268/356] =?UTF-8?q?[Chore]=20Game=20=EC=83=9D=EC=84=B1,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=9D=80=20Store=EB=A5=BC=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A0=20=EC=9C=A0=EC=A0=80=EB=A7=8C=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 24 +++++++++---------- .../domain/repository/StoreRepository.java | 5 ++++ .../exception/InvalidStoreIdException.java | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 1347cee1..a3f6bfdf 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -51,8 +51,8 @@ public class GameService { @Transactional public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findById(createGiftReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(createGiftReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); //store에 이미 존재하는 gametype인지 확인 List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); @@ -105,8 +105,8 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr @Transactional public ResponseEntity createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findById(createBasketballReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(createBasketballReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); //store에 이미 존재하는 gametype인지 확인 List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); @@ -161,8 +161,8 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask @Transactional public ResponseEntity createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findById(createRouletteReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(createRouletteReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); //store에 이미 존재하는 gametype인지 확인 List checkBenefitList = benefitRepository.findAllByStoreAndGameIsNotNull(store); @@ -219,11 +219,11 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet @Transactional public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(updateGiftReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); - Store store = storeRepository.findById(updateGiftReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); giftGame.updateGiftCount(updateGiftReq.getGiftCount()); @@ -257,11 +257,11 @@ public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq up @Transactional public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(updateBasketballReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); benefit.deleteGame(); - Store store = storeRepository.findById(updateBasketballReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); basketballGame.updateSuccessCount(updateBasketballReq.getSuccessCount()); @@ -298,11 +298,11 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask @Transactional public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Store store = storeRepository.findByIdAndMember(updateRouletteReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(rouletteGame.getGame()); benefitList.forEach(benefit -> benefit.deleteGame()); - Store store = storeRepository.findById(updateRouletteReq.getStoreId()).orElseThrow(InvalidStoreIdException::new); List newBenefitList = updateRouletteReq.getOptions().stream() .map(option -> Benefit.builder() diff --git a/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java b/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java index 17bfff83..d5ff3456 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java +++ b/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java @@ -1,9 +1,14 @@ package com.ttubeog.domain.store.domain.repository; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.store.domain.Store; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface StoreRepository extends JpaRepository { + + Optional findByIdAndMember(Long id, Member member); } diff --git a/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java b/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java index c612df13..d3b29ec7 100644 --- a/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java +++ b/src/main/java/com/ttubeog/domain/store/exception/InvalidStoreIdException.java @@ -3,6 +3,6 @@ public class InvalidStoreIdException extends RuntimeException { public InvalidStoreIdException() { - super("존재하지 않는 매장 Id값입니다."); + super("존재하지 않는 매장 Id값입니다. 또는 store에 권한이 없는 유저입니다."); } } \ No newline at end of file From 8937ffe1dffd7d49c3bb84e2a8d8b4917b96821c Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 14:45:02 +0900 Subject: [PATCH 269/356] =?UTF-8?q?[Feat]=20road=20domain=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GuestBookService.java | 6 +- .../domain/road/application/RoadService.java | 181 +++++++++++++++++- .../com/ttubeog/domain/road/domain/Road.java | 5 +- .../domain/repository/RoadRepository.java | 10 + .../dto/request/CreateRoadRequestDto.java | 4 - .../road/dto/response/RoadResponseDto.java | 8 +- .../exception/InvalidRoadIdException.java | 14 ++ .../road/presentation/RoadController.java | 7 +- ...ory.java => RoadCoordinateRepository.java} | 2 +- 9 files changed, 211 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java rename src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/{RoedCoordinateRepository.java => RoadCoordinateRepository.java} (81%) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 6c7d3d84..f25a4fcf 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -280,10 +280,14 @@ public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestB public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestBookId) { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); + if (!guestBook.getMember().equals(member)) { + throw new InvalidMemberException(); + } + guestBookRepository.delete(guestBook); imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 93871e74..49a5ea05 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -8,17 +8,24 @@ import com.ttubeog.domain.road.domain.RoadType; import com.ttubeog.domain.road.domain.repository.RoadRepository; import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.domain.road.dto.response.RoadResponseDto; import com.ttubeog.domain.road.exception.DuplicateRoadNameException; +import com.ttubeog.domain.road.exception.InvalidRoadIdException; import com.ttubeog.domain.road.exception.InvalidRoadTypeException; -import com.ttubeog.domain.road.presentation.RoadController; import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.roadcoordinate.domain.repository.RoadCoordinateRepository; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; +import com.ttubeog.domain.store.exception.InvalidStoreIdException; +import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,13 +39,15 @@ public class RoadService { private final RoadRepository roadRepository; + private final RoadCoordinateRepository roadCoordinateRepository; private final SpotRepository spotRepository; private final StoreRepository storeRepository; private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; - public ResponseEntity createGuestBook(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { + @Transactional + public ResponseEntity createRoad(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -62,33 +71,185 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateRoadR spot = spotRepository.findById(createRoadRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); - roadRepository.findBySpotAndName(spot, createRoadRequestDto.getName()).orElseThrow(DuplicateRoadNameException::new); + if (roadRepository.findBySpotAndName(spot, createRoadRequestDto.getName()).isPresent()) { + throw new DuplicateRoadNameException(); + } - road = Road.builder().build(); + road = Road.builder() + .roadType(RoadType.SPOT) + .spot(spot) + .member(member) + .name(createRoadRequestDto.getName()) + .roadCoordinateList(roadCoordinateList) + .build(); } else if (createRoadRequestDto.getRoadType().equals(RoadType.STORE)) { + store = storeRepository.findById(createRoadRequestDto.getStoreId()).orElseThrow(InvalidStoreIdException::new); + + if (roadRepository.findByStoreAndName(store, createRoadRequestDto.getName()).isPresent()) { + throw new DuplicateRoadNameException(); + } + + road = Road.builder() + .roadType(RoadType.STORE) + .store(store) + .member(member) + .name(createRoadRequestDto.getName()) + .roadCoordinateList(roadCoordinateList) + .build(); } else { throw new InvalidRoadTypeException(); } + for (RoadCoordinate roadCoordinate : roadCoordinateList) { + roadCoordinate.updateRoad(road); + } + + roadRepository.save(road); + + roadCoordinateRepository.saveAll(roadCoordinateList); + + List> roadCoordinateDoubleListResponse = new ArrayList<>(); + for (RoadCoordinate roadCoordinate : road.getRoadCoordinateList()) { + List roadCoordinateDoubleResponse = new ArrayList<>(); + roadCoordinateDoubleResponse.add(roadCoordinate.getLatitude()); + roadCoordinateDoubleResponse.add(roadCoordinate.getLongitude()); + roadCoordinateDoubleListResponse.add(roadCoordinateDoubleResponse); + } + + RoadResponseDto roadResponseDto; + + if (road.getRoadType().equals(RoadType.SPOT)) { + roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(RoadType.SPOT) + .spotId(road.getSpot().getId()) + .memberId(road.getMember().getId()) + .name(road.getName()) + .roadCoordinateDoubleList(roadCoordinateDoubleListResponse) + .build(); + } else if (road.getRoadType().equals(RoadType.STORE)) { + roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(RoadType.STORE) + .storeId(road.getStore().getId()) + .memberId(road.getMember().getId()) + .name(road.getName()) + .roadCoordinateDoubleList(roadCoordinateDoubleListResponse) + .build(); + } else { + throw new InvalidRoadTypeException(); + } + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(roadResponseDto) + .build(); - return null; + return ResponseEntity.ok(apiResponse); } - public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotId, Long pageNum) { + public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { - return null; + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Page roadPage = roadRepository.findAllBySpot_Id(spotId, PageRequest.of(pageNum, 1)); + + List roadResponseDtoList = new ArrayList<>(); + + for (Road road : roadPage) { + List> roadCoordinateDoubleList = new ArrayList<>(); + for (RoadCoordinate roadCoordinate : road.getRoadCoordinateList()) { + List roadCoordinateDouble = new ArrayList<>(); + roadCoordinateDouble.add(roadCoordinate.getLatitude()); + roadCoordinateDouble.add(roadCoordinate.getLongitude()); + roadCoordinateDoubleList.add(roadCoordinateDouble); + } + + RoadResponseDto roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(road.getRoadType()) + .spotId(road.getSpot().getId()) + .memberId(road.getMember().getId()) + .name(road.getName()) + .roadCoordinateDoubleList(roadCoordinateDoubleList) + .build(); + roadResponseDtoList.add(roadResponseDto); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(roadResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); } - public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long storeId, Long pageNum) { + public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - return null; + Page roadPage = roadRepository.findAllByStore_Id(storeId, PageRequest.of(pageNum, 1)); + + List roadResponseDtoList = new ArrayList<>(); + + for (Road road : roadPage) { + List> roadCoordinateDoubleList = new ArrayList<>(); + for (RoadCoordinate roadCoordinate : road.getRoadCoordinateList()) { + List roadCoordinateDouble = new ArrayList<>(); + roadCoordinateDouble.add(roadCoordinate.getLatitude()); + roadCoordinateDouble.add(roadCoordinate.getLongitude()); + roadCoordinateDoubleList.add(roadCoordinateDouble); + } + + RoadResponseDto roadResponseDto = RoadResponseDto.builder() + .id(road.getId()) + .roadType(road.getRoadType()) + .storeId(road.getStore().getId()) + .memberId(road.getMember().getId()) + .name(road.getName()) + .roadCoordinateDoubleList(roadCoordinateDoubleList) + .build(); + roadResponseDtoList.add(roadResponseDto); + } + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(roadResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); } + @Transactional public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { - return null; + Long memberId = jwtTokenProvider.getMemberId(request); + + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Road road = roadRepository.findById(roadId).orElseThrow(InvalidRoadIdException::new); + + if (!road.getMember().equals(member)) { + throw new InvalidMemberException(); + } + + List roadCoordinateList = road.getRoadCoordinateList(); + + roadRepository.delete(road); + + roadCoordinateRepository.deleteAll(roadCoordinateList); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(Message.builder().message("산책로를 삭제했습니다.").build()) + .build(); + + return ResponseEntity.ok(apiResponse); } } diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index 00d88bd7..3c2c3e16 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -43,10 +43,8 @@ public class Road extends BaseEntity { @OneToMany(mappedBy = "road", cascade = CascadeType.ALL) private List roadCoordinateList; - @Column(name = "time", nullable = false) - private String time; - public Road(Long id, RoadType roadType, Spot spot, Store store, Member member, String name, List roadCoordinateList, String time) { + public Road(Long id, RoadType roadType, Spot spot, Store store, Member member, String name, List roadCoordinateList) { this.id = id; this.roadType = roadType; this.spot = spot; @@ -54,6 +52,5 @@ public Road(Long id, RoadType roadType, Spot spot, Store store, Member member, S this.member = member; this.name = name; this.roadCoordinateList = roadCoordinateList; - this.time = time; } } diff --git a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java index adc18707..125bc905 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java +++ b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java @@ -2,6 +2,9 @@ import com.ttubeog.domain.road.domain.Road; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,4 +14,11 @@ public interface RoadRepository extends JpaRepository { Optional findBySpotAndName(Spot spot, String name); + + Optional findByStoreAndName(Store store, String name); + + Page findAllBySpot_Id(Long spotId, PageRequest pageRequest); + + Page findAllByStore_Id(Long storeId, PageRequest pageRequest); + } diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java index 7e271c67..5ddcdbf7 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -16,12 +16,8 @@ public class CreateRoadRequestDto { private Long storeId; - private Long memberId; - private String name; private List> roadCoordinateList; - private String time; - } diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java index 7e79b22a..70733b3c 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -1,6 +1,10 @@ package com.ttubeog.domain.road.dto.response; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.road.domain.RoadType; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import lombok.Builder; import lombok.Data; import lombok.Getter; @@ -24,8 +28,6 @@ public class RoadResponseDto { private String name; - private List> roadCoordinateList; - - private String time; + private List> roadCoordinateDoubleList; } diff --git a/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java new file mode 100644 index 00000000..9b361374 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/road/exception/InvalidRoadIdException.java @@ -0,0 +1,14 @@ +package com.ttubeog.domain.road.exception; + +import com.ttubeog.domain.member.exception.InvalidMemberException; + +public class InvalidRoadIdException extends RuntimeException { + + public InvalidRoadIdException() { + super("올바르지 않은 산책로 Id 입니다."); + } + + public InvalidRoadIdException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 982819f8..37a5cac6 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; import com.ttubeog.global.config.security.token.CurrentUser; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -25,7 +26,7 @@ public ResponseEntity createRoad( @CurrentUser HttpServletRequest request, @RequestBody CreateRoadRequestDto createRoadRequestDto ) throws JsonProcessingException { - return roadService.createGuestBook(request, createRoadRequestDto); + return roadService.createRoad(request, createRoadRequestDto); } @GetMapping("/{spotId}&{pageNum}") @@ -33,7 +34,7 @@ public ResponseEntity createRoad( public ResponseEntity findRoadBySpotId( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId, - @RequestParam(name = "pageNum") Long pageNum + @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { return roadService.findRoadBySpotId(request, spotId, pageNum); } @@ -43,7 +44,7 @@ public ResponseEntity findRoadBySpotId( public ResponseEntity findRoadByStoreId( @CurrentUser HttpServletRequest request, @RequestParam(name = "storeId") Long storeId, - @RequestParam(name = "pageNum") Long pageNum + @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { return roadService.findRoadByStoreId(request, storeId, pageNum); } diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java similarity index 81% rename from src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java rename to src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java index 40524218..c9ade995 100644 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoedCoordinateRepository.java +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java @@ -5,5 +5,5 @@ import org.springframework.stereotype.Repository; @Repository -public interface RoedCoordinateRepository extends JpaRepository { +public interface RoadCoordinateRepository extends JpaRepository { } From 1c884af9a6bbb6df0e7e40de3514b3cc4e52d79d Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 14:56:37 +0900 Subject: [PATCH 270/356] =?UTF-8?q?[Chore]=20Swagger=20Annotation=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/GuestBookController.java | 100 ++++++++++++- .../road/presentation/RoadController.java | 137 +++++++++++++++++- 2 files changed, 233 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index ede1b7b4..85c588fb 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -33,8 +33,8 @@ public class GuestBookController { * @return ResponseEntity -> GuestBookResponseDto * @throws JsonProcessingException json processing 에러 */ - @Operation(summary = "산책 스팟 생성", - description = "산책 스팟을 생성합니다.", + @Operation(summary = "방명록 생성 / createGuestBook", + description = "방명록 생성 API 입니다.", responses = {@ApiResponse( responseCode = "200", description = "OK", @@ -67,7 +67,38 @@ public ResponseEntity createGuestBook( } - + /** + * 산책 스팟에 속한 모든 방명록 페이징 조회 API + * @param request + * @param spotId + * @param pageNum + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "산책 스팟 소속 방명록 조회 API / findGuestBookBySpotId", + description = "산책 스팟에 속한 방명록을 페이징하여 조회하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = GuestBookResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @GetMapping("/{spotId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findGuestBookBySpotId( @@ -79,6 +110,38 @@ public ResponseEntity findGuestBookBySpotId( } + /** + * 매장에 속한 모든 방명록 페이징 조회 API + * @param request + * @param storeId + * @param pageNum + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "매장 소속 방명록 조회 API / findGuestBookByStoreId", + description = "매장에 속한 방명록을 페이징하여 조회하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = GuestBookResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @GetMapping("/{storeId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findGuestBookByStoreId( @@ -90,6 +153,37 @@ public ResponseEntity findGuestBookByStoreId( } + /** + * 방명록 삭제 API + * @param request + * @param guestBookId + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "방명록 삭제 API / deleteGuestBook", + description = " 방명록을 삭제하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = ResponseEntity.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @DeleteMapping("/{guestBookId}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteGuestBook( diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 37a5cac6..dd78b489 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -1,11 +1,18 @@ package com.ttubeog.domain.road.presentation; import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.road.application.RoadService; +import com.ttubeog.domain.road.domain.repository.RoadRepository; import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; +import com.ttubeog.domain.road.dto.response.RoadResponseDto; import com.ttubeog.global.config.security.token.CurrentUser; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +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.tags.Tag; -import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -20,6 +27,37 @@ public class RoadController { private final RoadService roadService; + /** + * 산책로 생성 API + * @param request + * @param createRoadRequestDto + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "산책로 생성 API / createRoad", + description = "산책로를 생성하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = RoadResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @PostMapping @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createRoad( @@ -29,6 +67,38 @@ public ResponseEntity createRoad( return roadService.createRoad(request, createRoadRequestDto); } + /** + * 산책 스팟에 속한 산책로 페이징 조회 API + * @param request + * @param spotId + * @param pageNum + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "산책 스팟 소속 산책로 페이징 조회 API", + description = "산책 스팟에 속한 산책로를 페이징하여 조회하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = RoadRepository.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @GetMapping("/{spotId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findRoadBySpotId( @@ -39,6 +109,39 @@ public ResponseEntity findRoadBySpotId( return roadService.findRoadBySpotId(request, spotId, pageNum); } + + /** + * 매장 소속 산책로 페이징 조회 API + * @param request + * @param storeId + * @param pageNum + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "매장 소속 산책로 페이징 조회 API", + description = "매장에 속한 산책로를 페이징하여 조회하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = RoadRepository.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @GetMapping("/{storeId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findRoadByStoreId( @@ -49,6 +152,38 @@ public ResponseEntity findRoadByStoreId( return roadService.findRoadByStoreId(request, storeId, pageNum); } + + /** + * 산책로 삭제 API + * @param request + * @param roadId + * @return + * @throws JsonProcessingException + */ + @Operation(summary = "산책로 삭제 API", + description = "산책로를 삭제하는 API 입니다.", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = ResponseEntity.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ) + } + ) @DeleteMapping("/{roadId}") @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteRoad( From 481730055e400e8888d218912f8fc822f3f534e0 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:01:46 +0900 Subject: [PATCH 271/356] =?UTF-8?q?[Chore]=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20HTTP=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/presentation/StoreController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index fe9eeb3c..50837858 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -112,7 +112,7 @@ public ResponseEntity likesStore( @ApiResponse(responseCode = "200", description = "게임 조회 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class))}), @ApiResponse(responseCode = "400", description = "게임 조회 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) - @PostMapping("/{storeId}/game") + @GetMapping("/{storeId}/game") public ResponseEntity findBenefitByStore( HttpServletRequest request, @PathVariable Long storeId From cbfdacdcf80bc3830af81f24d11cf6b654c364d0 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 16 Feb 2024 15:02:22 +0900 Subject: [PATCH 272/356] =?UTF-8?q?[Fix]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20isRegistered=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/auth/service/AuthService.java | 14 +++++++++----- .../domain/member/application/MemberService.java | 2 -- .../domain/store/application/StoreService.java | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 4cdc2bec..744c5d0e 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -96,15 +96,19 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String .map(existingMember -> { validateStatus(existingMember); String accessToken = issueAccessToken(existingMember); - String refreshToken = issueRefreshToken(); + String refreshToken = issueRefreshToken(existingMember); refreshTokenService.saveTokenInfo(existingMember.getId(), refreshToken, accessToken); - return new OAuthTokenResponse(accessToken, refreshToken, true); + if(existingMember.getNickname() == null) { + return new OAuthTokenResponse(accessToken, refreshToken, false); + } else { + return new OAuthTokenResponse(accessToken, refreshToken, true); + } }) .orElseGet(() -> { Member newMember = new Member(email, platform, Status.ACTIVE, platformId, false); Member savedMember = memberRepository.save(newMember); String accessToken = issueAccessToken(savedMember); - String refreshToken = issueRefreshToken(); + String refreshToken = issueRefreshToken(savedMember); refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); return new OAuthTokenResponse(accessToken, refreshToken, false); }); @@ -115,8 +119,8 @@ private String issueAccessToken(final Member findMember) { return jwtTokenProvider.createAccessToken(findMember.getId()); } - private String issueRefreshToken() { - return Token.createRefreshToken(); + private String issueRefreshToken(final Member findMember) { + return jwtTokenProvider.createRefreshToken(findMember.getId()); } private void validateStatus(final Member member) { diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 26c6b8bc..3cea7b67 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -91,8 +91,6 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN // 닉네임 업데이트 memberRepository.updateMemberNickname(produceNicknameRequest.getNickname(), memberId); - // 닉네임 1회 변경 true로 변경 - memberRepository.updateMemberNicknameChange(true, memberId); Optional checkMember = memberRepository.findById(memberId); Member member = checkMember.get(); diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 06310cad..23706b8d 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -226,6 +226,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { storeRepository.delete(store); + ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) From bf27cdd2c52a0ca3283f7234f305fe86a3676ab4 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 15:10:33 +0900 Subject: [PATCH 273/356] =?UTF-8?q?[Chore]=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/RoadCoordinateService.java | 4 ---- .../dto/request/CreateRoadCoordinateRequestDto.java | 9 --------- .../dto/response/RoadResponseCoordinateDto.java | 8 -------- 3 files changed, 21 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java delete mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java delete mode 100644 src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java b/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java deleted file mode 100644 index 0619b8cb..00000000 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/application/RoadCoordinateService.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.roadcoordinate.application; - -public class RoadCoordinateService { -} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java deleted file mode 100644 index aefc3378..00000000 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/request/CreateRoadCoordinateRequestDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ttubeog.domain.roadcoordinate.dto.request; - -import lombok.Data; - -@Data -public class CreateRoadCoordinateRequestDto { - - -} diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java b/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java deleted file mode 100644 index 04a99e42..00000000 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/dto/response/RoadResponseCoordinateDto.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ttubeog.domain.roadcoordinate.dto.response; - - -import lombok.Data; - -@Data -public class RoadResponseCoordinateDto { -} From a600e2aa3521bf995a3dc508020df5f7ad721316 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 16 Feb 2024 15:16:04 +0900 Subject: [PATCH 274/356] =?UTF-8?q?[Fix]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20nicknameChange=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/auth/service/AuthService.java | 5 +++++ .../com/ttubeog/domain/member/application/MemberService.java | 4 ++-- .../domain/member/dto/response/MemberNicknameRes.java | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index 744c5d0e..a1382d68 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -99,6 +99,11 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String String refreshToken = issueRefreshToken(existingMember); refreshTokenService.saveTokenInfo(existingMember.getId(), refreshToken, accessToken); if(existingMember.getNickname() == null) { + Member newMember = new Member(email, platform, Status.ACTIVE, platformId, false); + Member savedMember = memberRepository.save(newMember); + accessToken = issueAccessToken(savedMember); + refreshToken = issueRefreshToken(savedMember); + refreshTokenService.saveTokenInfo(savedMember.getId(), refreshToken, accessToken); return new OAuthTokenResponse(accessToken, refreshToken, false); } else { return new OAuthTokenResponse(accessToken, refreshToken, true); diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 3cea7b67..5217d9a5 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -76,7 +76,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() .id(checkMember.getId()) .nickname(checkMember.getNickname()) - .isChanged(checkMember.getNicknameChange()) + .nicknameChanged(checkMember.getNicknameChange()) .build(); ApiResponse apiResponse = ApiResponse.builder() @@ -98,7 +98,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() .id(member.getId()) .nickname(produceNicknameRequest.getNickname()) - .isChanged(member.getNicknameChange()) + .nicknameChanged(member.getNicknameChange()) .build(); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java index 60823b39..f65780a5 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java @@ -16,13 +16,13 @@ public class MemberNicknameRes { private Long id; private String nickname; - private Boolean isChanged; + private Boolean nicknameChanged; public static MemberNicknameRes toDto(Member member) { return MemberNicknameRes.builder() .id(member.getId()) .nickname(member.getNickname()) - .isChanged(member.getNicknameChange()) + .nicknameChanged(member.getNicknameChange()) .build(); } From e5872149f8ee1d30898c60e6d56d3209afa790c1 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 15:16:48 +0900 Subject: [PATCH 275/356] =?UTF-8?q?[Feat]=20Road,=20RoadCoordinate=20Entit?= =?UTF-8?q?y=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/road/domain/Road.java | 3 ++- .../domain/roadcoordinate/domain/RoadCoordinate.java | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/domain/Road.java b/src/main/java/com/ttubeog/domain/road/domain/Road.java index 3c2c3e16..b693d7b0 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/Road.java +++ b/src/main/java/com/ttubeog/domain/road/domain/Road.java @@ -6,6 +6,7 @@ import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; import jakarta.persistence.*; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -15,7 +16,7 @@ @Entity @Getter @Builder -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Road extends BaseEntity { @Id diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java index 4402e4cb..d1d20bf4 100644 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/RoadCoordinate.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.road.domain.Road; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.*; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -12,21 +13,21 @@ @Entity @Getter @Builder -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class RoadCoordinate extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "road_id") private Road road; - @Column(name = "latitude") + @Column(name = "latitude", nullable = false) private Double latitude; - @Column(name = "longitude") + @Column(name = "longitude", nullable = false) private Double longitude; public RoadCoordinate(Long id, Road road, Double latitude, Double longitude) { From 921b967d6398fcafb7dd223b307543c9490aff87 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 15:20:17 +0900 Subject: [PATCH 276/356] =?UTF-8?q?[Chore]=20Swagger=20Annotation=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/road/presentation/RoadController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index dd78b489..7dba249a 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -75,7 +75,7 @@ public ResponseEntity createRoad( * @return * @throws JsonProcessingException */ - @Operation(summary = "산책 스팟 소속 산책로 페이징 조회 API", + @Operation(summary = "산책 스팟 소속 산책로 페이징 조회 API / findRoadBySpotId", description = "산책 스팟에 속한 산책로를 페이징하여 조회하는 API 입니다.", responses = {@ApiResponse( responseCode = "200", @@ -118,7 +118,7 @@ public ResponseEntity findRoadBySpotId( * @return * @throws JsonProcessingException */ - @Operation(summary = "매장 소속 산책로 페이징 조회 API", + @Operation(summary = "매장 소속 산책로 페이징 조회 API / findRoadByStoreId", description = "매장에 속한 산책로를 페이징하여 조회하는 API 입니다.", responses = {@ApiResponse( responseCode = "200", @@ -160,7 +160,7 @@ public ResponseEntity findRoadByStoreId( * @return * @throws JsonProcessingException */ - @Operation(summary = "산책로 삭제 API", + @Operation(summary = "산책로 삭제 API / deleteRoadgi", description = "산책로를 삭제하는 API 입니다.", responses = {@ApiResponse( responseCode = "200", From 50994fb3a9b9bcd567041bc87de0b02ed6285356 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 16 Feb 2024 15:27:33 +0900 Subject: [PATCH 277/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=EC=8B=9C=20nicknameChange?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/member/application/MemberService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 5217d9a5..adbcb05a 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -90,7 +90,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN // 닉네임 업데이트 memberRepository.updateMemberNickname(produceNicknameRequest.getNickname(), memberId); - + memberRepository.updateMemberNicknameChange(true, memberId); Optional checkMember = memberRepository.findById(memberId); Member member = checkMember.get(); From 438ac56256a751fe4d4913862c1bef64fb570336 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 15:40:29 +0900 Subject: [PATCH 278/356] =?UTF-8?q?[Refac]=20GuestBook=20Service/Repositor?= =?UTF-8?q?y=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guestbook/application/GuestBookService.java | 12 ++++++++---- .../domain/repository/GuestBookRepository.java | 12 +++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index f25a4fcf..5f485e4c 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -143,7 +143,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest Float originStars = guestBookRepository.sumStarBySpotId(spot.getId()); - Long guestBookNum = guestBookRepository.countAllBySpot_Id(spot.getId()); + Long guestBookNum = guestBookRepository.countAllBySpot(spot); float updateStarValue; @@ -157,7 +157,7 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest Float originStars = guestBookRepository.sumStarByStoreId(store.getId()); - Long guestBookNum = guestBookRepository.countAllByStore_Id(store.getId()); + Long guestBookNum = guestBookRepository.countAllByStore(store); float updateStarValue; @@ -191,7 +191,9 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Page guestBookPage = guestBookRepository.findAllBySpot_Id(spotId, PageRequest.of(pageNum, 10)); + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + Page guestBookPage = guestBookRepository.findAllBySpot(spot, PageRequest.of(pageNum, 10)); List guestBookResponseDtoList = null; @@ -221,7 +223,9 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Page guestBookPage = guestBookRepository.findAllByStore_Id(storeId, PageRequest.of(pageNum, 10)); + Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); + + Page guestBookPage = guestBookRepository.findAllByStore(store, PageRequest.of(pageNum, 10)); List guestBookResponseDtoList = null; diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 0aac0e2d..44da0734 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -1,6 +1,8 @@ package com.ttubeog.domain.guestbook.domain.repository; import com.ttubeog.domain.guestbook.domain.GuestBook; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; @@ -13,20 +15,20 @@ @Repository public interface GuestBookRepository extends JpaRepository { - List findAllBySpot_Id(Long spotId); + List findAllBySpot(Store store); - Page findAllBySpot_Id(Long spotId, PageRequest pageRequest); + Page findAllBySpot(Spot spot, PageRequest pageRequest); - Long countAllBySpot_Id(Long spotId); + Long countAllBySpot(Spot spot); @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.spot.id = :spotId") Float sumStarBySpotId(@Param("spotId") Long spotId); List findAllByStore_Id(Long storeId); - Page findAllByStore_Id(Long storeId, PageRequest pageRequest); + Page findAllByStore(Store store, PageRequest pageRequest); - Long countAllByStore_Id(Long storeId); + Long countAllByStore(Store store); @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.store.id = :storeId") Float sumStarByStoreId(@Param("storeId") Long storeId); From bc02ccee9fed1e68dd7cf48e181b1aaa67ce5916 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Fri, 16 Feb 2024 16:14:01 +0900 Subject: [PATCH 279/356] =?UTF-8?q?[Feat]=20RoadRepository=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guestbook/domain/repository/GuestBookRepository.java | 4 ++-- .../java/com/ttubeog/domain/spot/application/SpotService.java | 2 +- .../com/ttubeog/domain/store/application/StoreService.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java index 44da0734..b21d56d3 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/repository/GuestBookRepository.java @@ -15,7 +15,7 @@ @Repository public interface GuestBookRepository extends JpaRepository { - List findAllBySpot(Store store); + List findAllBySpot(Spot spot); Page findAllBySpot(Spot spot, PageRequest pageRequest); @@ -24,7 +24,7 @@ public interface GuestBookRepository extends JpaRepository { @Query("SELECT SUM(g.star) FROM GuestBook g WHERE g.spot.id = :spotId") Float sumStarBySpotId(@Param("spotId") Long spotId); - List findAllByStore_Id(Long storeId); + List findAllByStore(Store store); Page findAllByStore(Store store, PageRequest pageRequest); diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 151f5b6e..1d654fcc 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -212,7 +212,7 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { List imageList = imageRepository.findBySpotId(spot.getId()); imageRepository.deleteAll(imageList); - List guestBookList = guestBookRepository.findAllBySpot_Id(spotId); + List guestBookList = guestBookRepository.findAllBySpot(spot); guestBookRepository.deleteAll(guestBookList); ApiResponse apiResponse = ApiResponse.builder() diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 06310cad..4a919c01 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -210,7 +210,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { benefitRepository.deleteAll(benefits); // 해당 매장과 연관된 방명록 삭제 - List guestBooks = guestBookRepository.findAllByStore_Id(storeId); + List guestBooks = guestBookRepository.findAllByStore(store); guestBookRepository.deleteAll(guestBooks); // 해당 매장과 연관된 좋아요 삭제 @@ -245,7 +245,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .stream() .map(Benefit::getType) .collect(Collectors.toList()); - Integer guestbookCount = guestBookRepository.countAllByStore_Id(storeId).intValue(); + Integer guestbookCount = guestBookRepository.countAllByStore(store).intValue(); Integer likesCount = likesRepository.countByStoreId(storeId); //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); From abce3c52afc90d7eb64a94c39a4b1c6c8bbaa9d7 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 17:43:38 +0900 Subject: [PATCH 280/356] =?UTF-8?q?[Fix]=20TimeLimit=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20LocalTime=EC=9C=BC=EB=A1=9C=20=EB=8B=A4=EC=8B=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DB와 연결에서 계속 문제가 터져서, 다시 원상태로 돌려놨습니다. --- .../com/ttubeog/domain/game/domain/BasketballGame.java | 8 +++++--- .../java/com/ttubeog/domain/game/domain/GiftGame.java | 8 +++++--- .../domain/game/dto/request/CreateBasketballReq.java | 6 ++++-- .../ttubeog/domain/game/dto/request/CreateGiftReq.java | 6 ++++-- .../domain/game/dto/request/UpdateBasketballReq.java | 6 ++++-- .../ttubeog/domain/game/dto/request/UpdateGiftReq.java | 6 ++++-- .../domain/game/dto/response/CreateBasketballRes.java | 8 +++++--- .../ttubeog/domain/game/dto/response/CreateGiftRes.java | 8 +++++--- .../com/ttubeog/domain/game/dto/response/FindGameRes.java | 8 +++++--- .../domain/game/dto/response/UpdateBasketballRes.java | 8 +++++--- .../ttubeog/domain/game/dto/response/UpdateGiftRes.java | 8 +++++--- 11 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java index a869483c..ddbe897f 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/BasketballGame.java @@ -7,6 +7,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalTime; + @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -23,7 +25,7 @@ public class BasketballGame extends BaseEntity { private Game game; @Column(name = "time_limit") - private Integer timeLimit; + private LocalTime timeLimit; @Column(name = "ball_count") private Integer ballCount; @@ -32,14 +34,14 @@ public class BasketballGame extends BaseEntity { private Integer successCount; @Builder - public BasketballGame(Game game, Integer timeLimit, Integer ballCount, Integer successCount) { + public BasketballGame(Game game, LocalTime timeLimit, Integer ballCount, Integer successCount) { this.game = game; this.timeLimit = timeLimit; this.ballCount = ballCount; this.successCount = successCount; } - public void updateTimeLimit(Integer timeLimit) { + public void updateTimeLimit(LocalTime timeLimit) { this.timeLimit = timeLimit; } diff --git a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java index 977b7512..13427268 100644 --- a/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java +++ b/src/main/java/com/ttubeog/domain/game/domain/GiftGame.java @@ -7,6 +7,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalTime; + @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @Entity @@ -23,19 +25,19 @@ public class GiftGame extends BaseEntity { private Game game; @Column(name = "time_limit") - private Integer timeLimit; + private LocalTime timeLimit; @Column(name = "gift_count") private Integer giftCount; @Builder - public GiftGame(Game game, int timeLimit, Integer giftCount) { + public GiftGame(Game game, LocalTime timeLimit, Integer giftCount) { this.game = game; this.timeLimit = timeLimit; this.giftCount = giftCount; } - public void updateTimeLimit(Integer timeLimit) { + public void updateTimeLimit(LocalTime timeLimit) { this.timeLimit = timeLimit; } diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java index 36db6e10..f635dfc1 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateBasketballReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalTime; + @Data @Schema(description = "CreateBasketballGameRequest") public class CreateBasketballReq { @@ -11,8 +13,8 @@ public class CreateBasketballReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java index 5c0f48f3..7dc73701 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/CreateGiftReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalTime; + @Data @Schema(description = "CreateGiftGameRequest") public class CreateGiftReq { @@ -11,8 +13,8 @@ public class CreateGiftReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java index 021f9750..0322572d 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalTime; + @Data @Schema(description = "UpdateBasketballGameRequest") public class UpdateBasketballReq { @@ -14,8 +16,8 @@ public class UpdateBasketballReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java index fe2665e4..711be017 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalTime; + @Data @Schema(description = "UpdateGiftGameRequest") public class UpdateGiftReq { @@ -14,8 +16,8 @@ public class UpdateGiftReq { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java index 821dae2c..42850735 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateBasketballRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.time.LocalTime; + @Data public class CreateBasketballRes { @@ -17,8 +19,8 @@ public class CreateBasketballRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; @@ -33,7 +35,7 @@ public class CreateBasketballRes { private BenefitType benefitType; @Builder - public CreateBasketballRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public CreateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java index d6065024..789ee446 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/CreateGiftRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.time.LocalTime; + @Data public class CreateGiftRes { @@ -17,8 +19,8 @@ public class CreateGiftRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -30,7 +32,7 @@ public class CreateGiftRes { private BenefitType benefitType; @Builder - public CreateGiftRes(Long benefitId, Long gameId, Long storeId, Integer timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public CreateGiftRes(Long benefitId, Long gameId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.benefitId = benefitId; this.gameId = gameId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java index 907d4fdc..38fb6bec 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/FindGameRes.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; + +import java.time.LocalTime; import java.util.List; @Data @@ -15,8 +17,8 @@ public class FindGameRes { @Schema(description = "종류", example = "roulette") private GameType type; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -34,7 +36,7 @@ public class FindGameRes { private List benefits; @Builder - public FindGameRes(Long gameId, GameType type, Integer timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options, List benefits) { + public FindGameRes(Long gameId, GameType type, LocalTime timeLimit, Integer giftCount, Integer ballCount, Integer successCount, List options, List benefits) { this.gameId = gameId; this.type = type; this.timeLimit = timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java index 77310860..d65245f8 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateBasketballRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.time.LocalTime; + @Data public class UpdateBasketballRes { @@ -17,8 +19,8 @@ public class UpdateBasketballRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "공 개수", example = "10") private Integer ballCount; @@ -33,7 +35,7 @@ public class UpdateBasketballRes { private BenefitType benefitType; @Builder - public UpdateBasketballRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { + public UpdateBasketballRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer ballCount, Integer successCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java index 6b0658db..90285725 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java +++ b/src/main/java/com/ttubeog/domain/game/dto/response/UpdateGiftRes.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Data; +import java.time.LocalTime; + @Data public class UpdateGiftRes { @@ -17,8 +19,8 @@ public class UpdateGiftRes { @Schema(description = "매장ID", example = "1") private Long storeId; - @Schema(description = "시간제한", example = "15") - private Integer timeLimit; + @Schema(description = "시간제한", example = "00:00:15") + private LocalTime timeLimit; @Schema(description = "선물개수", example = "3") private Integer giftCount; @@ -30,7 +32,7 @@ public class UpdateGiftRes { private BenefitType benefitType; @Builder - public UpdateGiftRes(Long gameId, Long benefitId, Long storeId, Integer timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { + public UpdateGiftRes(Long gameId, Long benefitId, Long storeId, LocalTime timeLimit, Integer giftCount, String benefitContent, BenefitType benefitType) { this.gameId = gameId; this.benefitId = benefitId; this.storeId = storeId; From 93df0db88fda06efef584c86524599f992c5f55f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 17:44:50 +0900 Subject: [PATCH 281/356] =?UTF-8?q?[Chore]=20repository=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/likes/application/LikesService.java | 4 ++-- .../domain/likes/domain/repository/LikesRepository.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 43a97070..22eb22e5 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -41,7 +41,7 @@ public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); - if (likesRepository.existsByMemberIdAndStoreId(member.getId(), storeId)) { + if (likesRepository.existsByMember_IdAndStore_Id(member.getId(), storeId)) { throw new AlreadyLikesException(); } @@ -68,7 +68,7 @@ public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(NonExistentSpotException::new); - if (likesRepository.existsByMemberIdAndSpotId(member.getId(), spotId)) { + if (likesRepository.existsByMember_IdAndSpot_Id(member.getId(), spotId)) { throw new AlreadyLikesException(); } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index b20926c2..69dcfa09 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -9,12 +9,12 @@ @Repository public interface LikesRepository extends JpaRepository { - List findByStoreId(Long storeId); + List findByStore_Id(Long storeId); - Integer countByStoreId(Long storeId); + Integer countByStore_Id(Long storeId); - boolean existsByMemberIdAndStoreId(Long memberId, Long StoreId); + boolean existsByMember_IdAndStore_Id(Long memberId, Long StoreId); - boolean existsByMemberIdAndSpotId(Long memberId, Long spotId); + boolean existsByMember_IdAndSpot_Id(Long memberId, Long spotId); } From a6cdbe4be333a5b6245e6ec01f4002b80f353a9e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 17:47:28 +0900 Subject: [PATCH 282/356] =?UTF-8?q?[Feat]=20DongArea=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/area/domain/DongArea.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java index 8631ad02..5f66e342 100644 --- a/src/main/java/com/ttubeog/domain/area/domain/DongArea.java +++ b/src/main/java/com/ttubeog/domain/area/domain/DongArea.java @@ -15,4 +15,6 @@ public class DongArea extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "dong_name") + private String dongName; } From 876f3a389b5ec26fb7ae9b7c422ae7cbd7b4468f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 17:56:16 +0900 Subject: [PATCH 283/356] =?UTF-8?q?[Chore]=20dongAreaId=20->=20dongName?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 27 ++++++++++--------- .../place/dto/request/SearchPlaceReq.java | 4 +-- .../place/dto/response/GetAllPlaceRes.java | 16 ++++++++--- .../place/dto/response/SearchPlaceRes.java | 8 +++--- .../store/application/StoreService.java | 4 +-- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 2edb71a0..f8d5b805 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -1,7 +1,7 @@ package com.ttubeog.domain.place.application; -import com.ttubeog.domain.auth.config.SecurityUtil; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; @@ -20,7 +20,6 @@ import com.ttubeog.global.payload.ApiResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -32,7 +31,7 @@ import java.util.List; import java.util.stream.Collectors; -import static com.ttubeog.domain.image.application.ImageService.getImageString; +import static org.aspectj.runtime.internal.Conversions.intValue; @RequiredArgsConstructor @@ -45,6 +44,7 @@ public class PlaceService { private final SpotRepository spotRepository; private final LikesRepository likesRepository; private final ImageRepository imageRepository; + private final GuestBookRepository guestBookRepository; private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; @@ -75,10 +75,10 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 현재 로그인 유저의 좋아요 여부 - Boolean storeLiked = likesRepository.existsByMemberIdAndStoreId(memberId, store.getId()); + Boolean storeLiked = likesRepository.existsByMember_IdAndStore_Id(memberId, store.getId()); PlaceType placeType = new PlaceType(true, false); - // 가장 인덱스가 작은 이미지 선택 + // 가장 인덱스가 작은 이미지 선택 (대표 이미지) List storeImages = imageRepository.findByStoreId(store.getId()); String representativeImageUrl = null; if (!storeImages.isEmpty()) { @@ -91,14 +91,14 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { return GetAllPlaceRes.builder() .placeId(store.getId()) .placeType(placeType) + .dongName(store.getDongArea().getDongName()) .memberId(store.getMember().getId()) .name(store.getName()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) .image(representativeImageUrl) - // .image(store.getImage()) .stars(store.getStars()) - // .guestbookCount(guestRepository.countByStoreId(store.getID())) + .guestbookCount(intValue(guestBookRepository.countAllByStore_Id(store.getId()))) .isFavorited(storeLiked) .createdAt(store.getCreatedAt()) .build(); @@ -110,10 +110,10 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 현재 로그인 유저의 좋아요 여부 - Boolean spotLiked = likesRepository.existsByMemberIdAndSpotId(memberId, spot.getId()); + Boolean spotLiked = likesRepository.existsByMember_IdAndSpot_Id(memberId, spot.getId()); PlaceType placeType = new PlaceType(false, true); - // 가장 인덱스가 작은 이미지 선택 + // 가장 인덱스가 작은 이미지 선택 (대표 이미지) List spotImages = imageRepository.findBySpotId(spot.getId()); String representativeImageUrl = null; if (!spotImages.isEmpty()) { @@ -133,7 +133,7 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { //.longitude(spot.getLongitude()) .image(representativeImageUrl) .stars(spot.getStars()) - //.guestbookCount(guestRepository.countBySpotId(spot.getID())) + .guestbookCount(intValue(guestBookRepository.countAllBySpot_Id(spot.getId()))) .isFavorited(spotLiked) .createdAt(spot.getCreatedAt()) .build(); @@ -271,17 +271,18 @@ public ResponseEntity getAllPlacesLatest(HttpServletRequest request, Pageable } // 장소 검색 + @Transactional public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq searchPlaceReq, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); List allPlaces = getAllPlaceResList(request, pageable); - // 검색어 포함 + 동일한 동ID 가진 장소 필터링 + // 검색어 포함 + 동일한 동이름을 가진 장소 필터링 List searchResult = new ArrayList<>(); for (GetAllPlaceRes place : allPlaces) { if (place.getName().contains(searchPlaceReq.getKeyword()) || - (place.getDongAreaId() != null && place.getDongAreaId().equals(searchPlaceReq.getDongAreaId()))) { + (place.getDongName() != null && place.getDongName().equals(searchPlaceReq.getDongName()))) { searchResult.add(place); } } @@ -312,7 +313,7 @@ public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq .map(place -> SearchPlaceRes.builder() .placeId(place.getPlaceId()) .placeType(place.getPlaceType()) - .dongAreaId(place.getDongAreaId()) + .dongName(place.getDongName()) .memberId(place.getMemberId()) .name(place.getName()) .latitude(place.getLatitude()) diff --git a/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java b/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java index 62a6fa36..485a4ce1 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java +++ b/src/main/java/com/ttubeog/domain/place/dto/request/SearchPlaceReq.java @@ -9,6 +9,6 @@ public class SearchPlaceReq { @Schema(description = "검색어") private String keyword; - @Schema(description = "지역(동) ID") - private Long dongAreaId; + @Schema(description = "지역(동) 이름") + private String dongName; } diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index 4f45290f..f6c003b6 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -16,8 +16,8 @@ public class GetAllPlaceRes { @Schema(description = "매장 또는 산책스팟") private PlaceType placeType; - @Schema(description = "동(지역) ID") - private Long dongAreaId; + @Schema(description = "지역(동) 이름") + private String dongName; @Schema(description = "등록유저 ID") private Long memberId; @@ -25,6 +25,9 @@ public class GetAllPlaceRes { @Schema(description = "장소 이름") private String name; + @Schema(description = "장소 설명") + private String info; + @Schema(description = "위도") private Double latitude; @@ -56,14 +59,15 @@ public class GetAllPlaceRes { private Double distance; @Builder - public GetAllPlaceRes(Long placeId, PlaceType placeType, Long dongAreaId, Long memberId, String name, Double latitude, Double longitude, + public GetAllPlaceRes(Long placeId, PlaceType placeType, String dongName, Long memberId, String name, String info, Double latitude, Double longitude, String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, LocalDateTime createdAt, Integer recommendationScore, Double distance) { this.placeId = placeId; this.placeType = placeType; - this.dongAreaId = dongAreaId; + this.dongName = dongName; this.memberId = memberId; this.name = name; + this.info = info; this.latitude = latitude; this.longitude = longitude; this.image = image; @@ -75,4 +79,8 @@ public GetAllPlaceRes(Long placeId, PlaceType placeType, Long dongAreaId, Long m this.recommendationScore = recommendationScore; this.distance = distance; } + + public Integer getLikesCount() { + return likesCount != null ? likesCount : 0; + } } diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java index 1fbd9be5..2e3e06ce 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java @@ -14,8 +14,8 @@ public class SearchPlaceRes { @Schema(description = "매장 또는 산책스팟") private PlaceType placeType; - @Schema(description = "동(지역) ID") - private Long dongAreaId; + @Schema(description = "지역(동) 이름") + private String dongName; @Schema(description = "등록유저 ID") private Long memberId; @@ -45,11 +45,11 @@ public class SearchPlaceRes { private Boolean isFavorited; @Builder - public SearchPlaceRes(Long placeId, PlaceType placeType, Long dongAreaId, Long memberId, String name, Double latitude, Double longitude, + public SearchPlaceRes(Long placeId, PlaceType placeType, String dongName, Long memberId, String name, Double latitude, Double longitude, String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { this.placeId = placeId; this.placeType = placeType; - this.dongAreaId = dongAreaId; + this.dongName = dongName; this.memberId = memberId; this.name = name; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 06310cad..f5733319 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -214,7 +214,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { guestBookRepository.deleteAll(guestBooks); // 해당 매장과 연관된 좋아요 삭제 - List likes = likesRepository.findByStoreId(storeId); + List likes = likesRepository.findByStore_Id(storeId); likesRepository.deleteAll(likes); // 해당 매장과 연관된 이미지 삭제 @@ -246,7 +246,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .map(Benefit::getType) .collect(Collectors.toList()); Integer guestbookCount = guestBookRepository.countAllByStore_Id(storeId).intValue(); - Integer likesCount = likesRepository.countByStoreId(storeId); + Integer likesCount = likesRepository.countByStore_Id(storeId); //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() From 197523ec5b40465e5211078ac46bcfc2793ca04e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 17:58:35 +0900 Subject: [PATCH 284/356] =?UTF-8?q?[Remove]=20PlaceRepository=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/place/domain/repository/PlaceRepository.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java diff --git a/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java b/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java deleted file mode 100644 index 9b2e31b6..00000000 --- a/src/main/java/com/ttubeog/domain/place/domain/repository/PlaceRepository.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ttubeog.domain.place.domain.repository; - -public interface PlaceRepository { -} From 370649f75274806450f40e295e36cf482c382079 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 18:20:43 +0900 Subject: [PATCH 285/356] =?UTF-8?q?[Refac]=20GuestBookRepository=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/place/application/PlaceService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index f8d5b805..c928d943 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -2,7 +2,6 @@ import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; -import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.likes.domain.repository.LikesRepository; @@ -45,7 +44,6 @@ public class PlaceService { private final LikesRepository likesRepository; private final ImageRepository imageRepository; private final GuestBookRepository guestBookRepository; - private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; public List getPageOfPlaces(List places, int page, int size) { @@ -98,7 +96,7 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { .longitude(store.getLongitude()) .image(representativeImageUrl) .stars(store.getStars()) - .guestbookCount(intValue(guestBookRepository.countAllByStore_Id(store.getId()))) + .guestbookCount(intValue(guestBookRepository.countAllByStore(store))) .isFavorited(storeLiked) .createdAt(store.getCreatedAt()) .build(); @@ -133,7 +131,7 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { //.longitude(spot.getLongitude()) .image(representativeImageUrl) .stars(spot.getStars()) - .guestbookCount(intValue(guestBookRepository.countAllBySpot_Id(spot.getId()))) + .guestbookCount(intValue(guestBookRepository.countAllBySpot(spot))) .isFavorited(spotLiked) .createdAt(spot.getCreatedAt()) .build(); From 895a180a3f7488e8f09b4e546027c9a475f8c47c Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 18:27:33 +0900 Subject: [PATCH 286/356] =?UTF-8?q?[Refac]=20Likes=20Service/Repository=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/likes/application/LikesService.java | 4 ++-- .../likes/domain/repository/LikesRepository.java | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 22eb22e5..267134e4 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -41,7 +41,7 @@ public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); - if (likesRepository.existsByMember_IdAndStore_Id(member.getId(), storeId)) { + if (likesRepository.existsByMemberAndStore(member, store)) { throw new AlreadyLikesException(); } @@ -68,7 +68,7 @@ public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Spot spot = spotRepository.findById(spotId).orElseThrow(NonExistentSpotException::new); - if (likesRepository.existsByMember_IdAndSpot_Id(member.getId(), spotId)) { + if (likesRepository.existsByMemberAndSpot(member, spot)) { throw new AlreadyLikesException(); } diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index 69dcfa09..c6323d89 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.likes.domain.repository; import com.ttubeog.domain.likes.domain.Likes; +import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,12 +12,12 @@ @Repository public interface LikesRepository extends JpaRepository { - List findByStore_Id(Long storeId); + List findByStore(Store store); - Integer countByStore_Id(Long storeId); + Integer countByStore(Store store); - boolean existsByMember_IdAndStore_Id(Long memberId, Long StoreId); + boolean existsByMemberAndStore(Member member, Store store); - boolean existsByMember_IdAndSpot_Id(Long memberId, Long spotId); + boolean existsByMemberAndSpot(Member member, Spot spot); } From cfa0e54cb36884d02cd78c118855ce2ba73279ae Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 16 Feb 2024 18:30:36 +0900 Subject: [PATCH 287/356] =?UTF-8?q?[Refac]=20LikesRepository=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/place/application/PlaceService.java | 9 +++++---- .../ttubeog/domain/store/application/StoreService.java | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index c928d943..1e26860a 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.likes.domain.repository.LikesRepository; +import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.place.domain.PlaceType; @@ -70,10 +71,10 @@ public List getAllPlaceResList(HttpServletRequest request, Pagea private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 현재 로그인 유저의 좋아요 여부 - Boolean storeLiked = likesRepository.existsByMember_IdAndStore_Id(memberId, store.getId()); + Boolean storeLiked = likesRepository.existsByMemberAndStore(member, store); PlaceType placeType = new PlaceType(true, false); // 가장 인덱스가 작은 이미지 선택 (대표 이미지) @@ -105,10 +106,10 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); // 현재 로그인 유저의 좋아요 여부 - Boolean spotLiked = likesRepository.existsByMember_IdAndSpot_Id(memberId, spot.getId()); + Boolean spotLiked = likesRepository.existsByMemberAndSpot(member, spot); PlaceType placeType = new PlaceType(false, true); // 가장 인덱스가 작은 이미지 선택 (대표 이미지) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 4a919c01..76607185 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -214,7 +214,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { guestBookRepository.deleteAll(guestBooks); // 해당 매장과 연관된 좋아요 삭제 - List likes = likesRepository.findByStoreId(storeId); + List likes = likesRepository.findByStore(store); likesRepository.deleteAll(likes); // 해당 매장과 연관된 이미지 삭제 @@ -238,7 +238,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(NonExistentStoreException::new); List storeBenefits = benefitRepository.findByStoreId(storeId) @@ -246,8 +246,8 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .map(Benefit::getType) .collect(Collectors.toList()); Integer guestbookCount = guestBookRepository.countAllByStore(store).intValue(); - Integer likesCount = likesRepository.countByStoreId(storeId); - //Boolean isFavorited = likesRepository.existsByMemberIdAndStoreId(memberId, storeId); + Integer likesCount = likesRepository.countByStore(store); + Boolean isFavorited = likesRepository.existsByMemberAndStore(member, store); GetStoreDetailRes getStoreDetailRes = GetStoreDetailRes.builder() .storeId(storeId) @@ -264,7 +264,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .storeBenefits(storeBenefits) .guestbookCount(guestbookCount) .likesCount(likesCount) - //.isFavorited(isFavorited) + .isFavorited(isFavorited) .build(); ApiResponse apiResponse = ApiResponse.builder() From 47a8275140a98aa6315628038cb57d6a79f2a810 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 16 Feb 2024 18:40:23 +0900 Subject: [PATCH 288/356] =?UTF-8?q?[Refactor]=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=20storeID=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 생각해보니 게임을 수정할 땐 gameId 외에 storeID등은 불필요해보여서 삭제했습니다 --- .../domain/game/application/GameService.java | 21 ++++++++++++++++--- .../game/dto/request/UpdateBasketballReq.java | 3 --- .../game/dto/request/UpdateGiftReq.java | 3 --- .../game/dto/request/UpdateRouletteReq.java | 3 --- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index a3f6bfdf..0e9eaa8e 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -220,9 +220,14 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findByIdAndMember(updateGiftReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(giftGame.getGame()).orElseThrow(NonExistentBenefitException::new); + + Store store = benefit.getStore(); + if (!store.getMember().equals(member)) { + throw new InvalidStoreIdException(); + } + benefit.deleteGame(); giftGame.updateTimeLimit(updateGiftReq.getTimeLimit()); @@ -258,9 +263,14 @@ public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq up public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findByIdAndMember(updateBasketballReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); Benefit benefit = benefitRepository.findByGame(basketballGame.getGame()).orElseThrow(NonExistentBenefitException::new); + + Store store = benefit.getStore(); + if (!store.getMember().equals(member)) { + throw new InvalidStoreIdException(); + } + benefit.deleteGame(); basketballGame.updateBallCount(updateBasketballReq.getBallCount()); @@ -299,9 +309,14 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Store store = storeRepository.findByIdAndMember(updateRouletteReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); List benefitList = benefitRepository.findAllByGame(rouletteGame.getGame()); + + Store store = benefitList.get(0).getStore(); + if (!store.getMember().equals(member)) { + throw new InvalidStoreIdException(); + } + benefitList.forEach(benefit -> benefit.deleteGame()); List newBenefitList = updateRouletteReq.getOptions().stream() diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java index 0322572d..78afa32b 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateBasketballReq.java @@ -13,9 +13,6 @@ public class UpdateBasketballReq { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "매장ID", example = "1") - private Long storeId; - @Schema(description = "시간제한", example = "00:00:15") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java index 711be017..3a6614d5 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateGiftReq.java @@ -13,9 +13,6 @@ public class UpdateGiftReq { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "매장ID", example = "1") - private Long storeId; - @Schema(description = "시간제한", example = "00:00:15") private LocalTime timeLimit; diff --git a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java index 5ca9cb02..570f3857 100644 --- a/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java +++ b/src/main/java/com/ttubeog/domain/game/dto/request/UpdateRouletteReq.java @@ -12,9 +12,6 @@ public class UpdateRouletteReq { @Schema(description = "게임 ID", example = "1") private Long gameId; - @Schema(description = "매장ID", example = "1") - private Long storeId; - @Schema(description = "혜택 타입", example = "SALE") private BenefitType benefitType; From 7231e04045ec5fa3fde6fa554299f9fc6cc699db Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 17 Feb 2024 04:40:09 +0900 Subject: [PATCH 289/356] =?UTF-8?q?[Feat]=20Spot=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=88=98=20=ED=99=95=EC=9D=B8=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/likes/domain/repository/LikesRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java index c6323d89..05aa044f 100644 --- a/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java +++ b/src/main/java/com/ttubeog/domain/likes/domain/repository/LikesRepository.java @@ -15,6 +15,10 @@ public interface LikesRepository extends JpaRepository { List findByStore(Store store); Integer countByStore(Store store); + + List findBySpot(Spot spot); + + Integer countBySpot(Spot spot); boolean existsByMemberAndStore(Member member, Store store); From 5863fc7476e62f72628efc1690e7f163c8d0786e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 17 Feb 2024 04:43:31 +0900 Subject: [PATCH 290/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EA=B2=8C=EC=9E=84=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../place/application/PlaceService.java | 32 +++++++++++++++++-- .../place/dto/response/GetAllPlaceRes.java | 8 +++-- .../place/dto/response/SearchPlaceRes.java | 8 +++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 1e26860a..5086357b 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -1,6 +1,10 @@ package com.ttubeog.domain.place.application; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; +import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; +import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; @@ -25,6 +29,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -45,6 +50,9 @@ public class PlaceService { private final LikesRepository likesRepository; private final ImageRepository imageRepository; private final GuestBookRepository guestBookRepository; + private final BenefitRepository benefitRepository; + private final MemberBenefitRepository memberBenefitRepository; + private final JwtTokenProvider jwtTokenProvider; public List getPageOfPlaces(List places, int page, int size) { @@ -62,6 +70,7 @@ public List getAllPlaceResList(HttpServletRequest request, Pagea places.addAll(stores.stream().map(store -> mapStoreToDto(request, store)).collect(Collectors.toList())); List spots = spotRepository.findAll(); places.addAll(spots.stream().map(spot -> mapSpotToDto(request, spot)).collect(Collectors.toList())); + int page = pageable.getPageNumber(); int size = pageable.getPageSize(); @@ -73,9 +82,17 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + // 장소 타입 + PlaceType placeType = new PlaceType(true, false); + // 현재 로그인 유저의 좋아요 여부 Boolean storeLiked = likesRepository.existsByMemberAndStore(member, store); - PlaceType placeType = new PlaceType(true, false); + + Integer likesCount = likesRepository.countByStore(store); + + // 해당 매장의 혜택 여부 + List checkBenefitList = benefitRepository.findByStore(store); + Boolean hasGame = memberBenefitRepository.existsByBenefitInAndMemberAndCreatedAtIsAfter(checkBenefitList, member, LocalDateTime.now().minusMonths(1)); // 가장 인덱스가 작은 이미지 선택 (대표 이미지) List storeImages = imageRepository.findByStoreId(store.getId()); @@ -93,13 +110,16 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { .dongName(store.getDongArea().getDongName()) .memberId(store.getMember().getId()) .name(store.getName()) + .info(store.getInfo()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) .image(representativeImageUrl) .stars(store.getStars()) .guestbookCount(intValue(guestBookRepository.countAllByStore(store))) .isFavorited(storeLiked) + .likesCount(likesCount) .createdAt(store.getCreatedAt()) + .hasGame(hasGame) .build(); } @@ -108,9 +128,12 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + PlaceType placeType = new PlaceType(false, true); + // 현재 로그인 유저의 좋아요 여부 Boolean spotLiked = likesRepository.existsByMemberAndSpot(member, spot); - PlaceType placeType = new PlaceType(false, true); + + Integer likesCount = likesRepository.countBySpot(spot); // 가장 인덱스가 작은 이미지 선택 (대표 이미지) List spotImages = imageRepository.findBySpotId(spot.getId()); @@ -127,13 +150,15 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { .placeType(placeType) .memberId(spot.getMember().getId()) .name(spot.getName()) - //위도, 경도 double로 변경 필요 + .info(spot.getInfo()) + // 위도, 경도 double로 변경 필요 //.latitude(spot.getLatitude()) //.longitude(spot.getLongitude()) .image(representativeImageUrl) .stars(spot.getStars()) .guestbookCount(intValue(guestBookRepository.countAllBySpot(spot))) .isFavorited(spotLiked) + .likesCount(likesCount) .createdAt(spot.getCreatedAt()) .build(); } @@ -322,6 +347,7 @@ public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq .guestbookCount(place.getGuestbookCount()) .likesCount(place.getLikesCount()) .isFavorited(place.getIsFavorited()) + .hasGame(place.getHasGame()) .build()) .collect(Collectors.toList()); diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java index f6c003b6..21b1f9f0 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/GetAllPlaceRes.java @@ -58,10 +58,13 @@ public class GetAllPlaceRes { @Schema(description = "사용자와의 거리") private Double distance; + @Schema(description = "게임 존재 여부") + private Boolean hasGame; + @Builder public GetAllPlaceRes(Long placeId, PlaceType placeType, String dongName, Long memberId, String name, String info, Double latitude, Double longitude, String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, - LocalDateTime createdAt, Integer recommendationScore, Double distance) { + LocalDateTime createdAt, Integer recommendationScore, Double distance, Boolean hasGame) { this.placeId = placeId; this.placeType = placeType; this.dongName = dongName; @@ -78,9 +81,10 @@ public GetAllPlaceRes(Long placeId, PlaceType placeType, String dongName, Long m this.createdAt = createdAt; this.recommendationScore = recommendationScore; this.distance = distance; + this.hasGame = hasGame; } public Integer getLikesCount() { return likesCount != null ? likesCount : 0; } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java index 2e3e06ce..58610edc 100644 --- a/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java +++ b/src/main/java/com/ttubeog/domain/place/dto/response/SearchPlaceRes.java @@ -44,9 +44,12 @@ public class SearchPlaceRes { @Schema(description = "좋아요 여부") private Boolean isFavorited; + @Schema(description = "게임 존재 여부") + private Boolean hasGame; + @Builder public SearchPlaceRes(Long placeId, PlaceType placeType, String dongName, Long memberId, String name, Double latitude, Double longitude, - String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { + String image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited, Boolean hasGame) { this.placeId = placeId; this.placeType = placeType; this.dongName = dongName; @@ -59,5 +62,6 @@ public SearchPlaceRes(Long placeId, PlaceType placeType, String dongName, Long m this.guestbookCount = guestbookCount; this.likesCount = likesCount; this.isFavorited = isFavorited; + this.hasGame = hasGame; } -} +} \ No newline at end of file From f336a6e61c02fd3b41937f0c7dbfcdcc5c5eb209 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 17 Feb 2024 04:45:10 +0900 Subject: [PATCH 291/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/place/application/PlaceService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 5086357b..91863493 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -4,7 +4,6 @@ import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; -import com.ttubeog.domain.benefit.exception.OverlappingBenefitException; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; From c7eaede34f0e4bfe5e29d5f212ca93a0e77b53d9 Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 17 Feb 2024 19:35:54 +0900 Subject: [PATCH 292/356] =?UTF-8?q?[Feat]=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?2=EB=B2=88=EA=B9=8C=EC=A7=80=20=EC=84=A4=EC=A0=95=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/AuthService.java | 6 +- .../member/application/MemberService.java | 8 ++- .../ttubeog/domain/member/domain/Member.java | 6 +- .../domain/repository/MemberRepository.java | 3 +- .../dto/response/MemberNicknameRes.java | 2 +- .../member/presentation/MemberController.java | 66 +++++++++++++++++++ .../domain/spot/application/SpotService.java | 6 +- .../com/ttubeog/domain/spot/domain/Spot.java | 9 ++- .../dto/request/CreateSpotRequestDto.java | 2 +- .../dto/request/UpdateSpotRequestDto.java | 2 +- .../spot/dto/response/SpotResponseDto.java | 2 +- 11 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java index a1382d68..4ff6a8be 100644 --- a/src/main/java/com/ttubeog/domain/auth/service/AuthService.java +++ b/src/main/java/com/ttubeog/domain/auth/service/AuthService.java @@ -58,7 +58,7 @@ public KakaoTokenResponse kakaoOAuthLogin(String accessToken) { .memberNumber(String.valueOf(memberInfo.getId())) .platform(Platform.KAKAO) .status(Status.ACTIVE) - .nicknameChange(false) + .nicknameChange(0) .build(); memberRepository.save(member); @@ -99,7 +99,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String String refreshToken = issueRefreshToken(existingMember); refreshTokenService.saveTokenInfo(existingMember.getId(), refreshToken, accessToken); if(existingMember.getNickname() == null) { - Member newMember = new Member(email, platform, Status.ACTIVE, platformId, false); + Member newMember = new Member(email, platform, Status.ACTIVE, platformId, 0); Member savedMember = memberRepository.save(newMember); accessToken = issueAccessToken(savedMember); refreshToken = issueRefreshToken(savedMember); @@ -110,7 +110,7 @@ private OAuthTokenResponse generateOAuthTokenResponse(Platform platform, String } }) .orElseGet(() -> { - Member newMember = new Member(email, platform, Status.ACTIVE, platformId, false); + Member newMember = new Member(email, platform, Status.ACTIVE, platformId, 0); Member savedMember = memberRepository.save(newMember); String accessToken = issueAccessToken(savedMember); String refreshToken = issueRefreshToken(savedMember); diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index adbcb05a..3647d6bd 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -11,7 +11,6 @@ import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.domain.member.dto.response.MemberNicknameRes; -import com.ttubeog.domain.member.exception.AlreadyChangeNicknameException; import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -70,7 +69,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN Optional checkMemberIsChanged = memberRepository.findById(memberId); if (checkMemberIsChanged.isPresent()) { Member member = checkMemberIsChanged.get(); - if (member.isNickNameChanged()) { + if (member.isNickNameChanged() == 2) { Member checkMember = memberRepository.findById(memberId).get(); MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() @@ -90,10 +89,13 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN // 닉네임 업데이트 memberRepository.updateMemberNickname(produceNicknameRequest.getNickname(), memberId); - memberRepository.updateMemberNicknameChange(true, memberId); Optional checkMember = memberRepository.findById(memberId); Member member = checkMember.get(); + Integer nickNameChanged = member.isNickNameChanged(); + Integer newNicknameChanged = nickNameChanged += 1; + memberRepository.updateMemberNicknameChange(newNicknameChanged, memberId); + MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() .id(member.getId()) diff --git a/src/main/java/com/ttubeog/domain/member/domain/Member.java b/src/main/java/com/ttubeog/domain/member/domain/Member.java index 953d1c3b..27bf602d 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/Member.java +++ b/src/main/java/com/ttubeog/domain/member/domain/Member.java @@ -46,10 +46,10 @@ public class Member extends BaseEntity { private String refreshToken; @Column(name = "nickname_changed") - private Boolean nicknameChange; + private Integer nicknameChange; - public Member(String email, Platform platform, Status status, String memberNumber, Boolean nicknameChange) { + public Member(String email, Platform platform, Status status, String memberNumber, Integer nicknameChange) { this.email = email; this.platform = platform; this.platformId = platformId; @@ -64,7 +64,7 @@ public Member(Status status) { public boolean isRegisteredOAuthMember() { return nickname != null; } - public boolean isNickNameChanged() { return nicknameChange; } + public Integer isNickNameChanged() { return nicknameChange; } public void updateName(String name) { this.nickname = name; diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 9992126d..6eddef82 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -24,6 +24,7 @@ public interface MemberRepository extends JpaRepository{ List findByStatus(Status status); + Optional findByPlatformAndPlatformId(Platform platform, String platformId); Optional findByRefreshToken(String refreshToken); @@ -39,7 +40,7 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("update Member as m set m.nicknameChange = :nicknameChange where m.id = :memberId") - void updateMemberNicknameChange(@Param("nicknameChange") Boolean nicknameChange, @Param("memberId") Long memberId); + void updateMemberNicknameChange(@Param("nicknameChange") Integer nicknameChange, @Param("memberId") Long memberId); Boolean existsByNickname(String nickname); diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java index f65780a5..30ace72e 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java @@ -16,7 +16,7 @@ public class MemberNicknameRes { private Long id; private String nickname; - private Boolean nicknameChanged; + private Integer nicknameChanged; public static MemberNicknameRes toDto(Member member) { return MemberNicknameRes.builder() diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index b3e623bc..5bfc8870 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -1,13 +1,21 @@ package com.ttubeog.domain.member.presentation; +import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailRes; import com.ttubeog.domain.member.dto.response.MemberNicknameRes; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.dto.response.SpotResponseDto; +import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; +import com.ttubeog.domain.spot.exception.InvalidDongAreaException; +import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; +import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -120,4 +128,62 @@ public ResponseEntity logout( // } // return responseEntity; // } + + /** + * 내 산책로 조회 API + * @param request 유저 검증 + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException + */ + @Operation(summary = "내 산책 스팟 조회 API", + description = "내가 등록한 산책 스팟을 조회합니다.\n", + responses = {@ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - AlreadyExistsSpotException", + description = "이미 존재하는 산책 장소명입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidDongAreaException", + description = "유효하지 않은 지역 정보입니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) + ) + } + ), + } + ) + @GetMapping("/{memberId}/spot") + public ResponseEntity getMySpotList( + @CurrentUser HttpServletRequest request, + @RequestParam(name = "memberId") Long memberId + ) throws JsonProcessingException { + return null; + } } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 1d654fcc..68b151ef 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -59,7 +59,7 @@ private ResponseEntity getResponseEntity(Spot spot) { SpotResponseDto createSpotResponseDto = SpotResponseDto.builder() .id(spot.getId()) .memberId(spot.getMember().getId()) - .dongAreaId(spot.getDongArea().getId()) + .dongAreaId(spot.getDongArea()) .detailAddress(spot.getDetailAddress()) .name(spot.getName()) .info(spot.getInfo()) @@ -91,7 +91,7 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques } // 지역코드가 유효한지 체크 - DongArea dongArea = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); + String dongArea = String.valueOf(dongAreaRepository.findById(Long.valueOf(createSpotRequestDto.getDongAreaId())).orElseThrow(InvalidDongAreaException::new)); // 산책 스팟 이미지가 1~10개 사이인지 체크 if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { @@ -162,7 +162,7 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd } // 수정하려는 지역코드가 유효한지 체크 - DongArea dongArea = dongAreaRepository.findById(updateSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); + String dongArea = String.valueOf(dongAreaRepository.findById(Long.valueOf(updateSpotRequestDto.getDongAreaId())).orElseThrow(InvalidDongAreaException::new)); // 수정하려는 산책 스팟 이미지가 1~10개 사이인지 체크 if (updateSpotRequestDto.getImage().isEmpty() || updateSpotRequestDto.getImage().size() > 10) { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 9410b862..3b0fa1aa 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -53,15 +53,14 @@ public class Spot extends BaseEntity { private Member member; @Schema(description = "지역 코드", example = "DongArea Entity") - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "dong_area_id", nullable = false) - private DongArea dongArea; + @Column(name = "dong_area_id", nullable = false) + private String dongArea; @Schema(description = "상세 주소", example = "301호") @Column(name = "detail_address", nullable = false) private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, DongArea dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, String dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; @@ -73,7 +72,7 @@ public Spot(Long id, String name, String info, Float latitude, Float longitude, this.detailAddress = detailAddress; } - public void updateSpot(String name, String info, Float latitude, Float longitude, DongArea dongArea, String detailAddress) { + public void updateSpot(String name, String info, Float latitude, Float longitude, String dongArea, String detailAddress) { this.name = name; this.info = info; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 4b4089de..148fcea5 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -17,7 +17,7 @@ public class CreateSpotRequestDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 84debe42..0ffac459 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -16,7 +16,7 @@ public class UpdateSpotRequestDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 794d5d01..64ae4c4c 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -21,7 +21,7 @@ public class SpotResponseDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; From f257677103978a294e87f364f759f09ff98a0a25 Mon Sep 17 00:00:00 2001 From: arinming Date: Sat, 17 Feb 2024 20:01:00 +0900 Subject: [PATCH 293/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=EC=9E=A5=EC=86=8C?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20Response=20Dto=20=EC=83=9D=EC=84=B1=20(?= =?UTF-8?q?#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 16 ++++++------ ...berDetailRes.java => MemberDetailDto.java} | 6 ++--- ...icknameRes.java => MemberNicknameDto.java} | 7 +++--- .../member/dto/response/MemberPlaceDto.java | 25 +++++++++++++++++++ .../member/presentation/MemberController.java | 17 ++++++------- 5 files changed, 46 insertions(+), 25 deletions(-) rename src/main/java/com/ttubeog/domain/member/dto/response/{MemberDetailRes.java => MemberDetailDto.java} (82%) rename src/main/java/com/ttubeog/domain/member/dto/response/{MemberNicknameRes.java => MemberNicknameDto.java} (74%) create mode 100644 src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 3647d6bd..23596d4c 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -9,8 +9,8 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.domain.member.dto.response.MemberNicknameRes; +import com.ttubeog.domain.member.dto.response.MemberDetailDto; +import com.ttubeog.domain.member.dto.response.MemberNicknameDto; import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -47,7 +47,7 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { DefaultAssert.isOptionalPresent(checkMember); Member member = checkMember.get(); - MemberDetailRes memberDetailRes = MemberDetailRes.builder() + MemberDetailDto memberDetailDto = MemberDetailDto.builder() .id(member.getId()) .name(member.getNickname()) .platform(member.getPlatform()) @@ -55,7 +55,7 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(memberDetailRes) + .information(memberDetailDto) .build(); return ResponseEntity.ok(apiResponse); @@ -72,7 +72,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN if (member.isNickNameChanged() == 2) { Member checkMember = memberRepository.findById(memberId).get(); - MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() + MemberNicknameDto memberNicknameDto = MemberNicknameDto.builder() .id(checkMember.getId()) .nickname(checkMember.getNickname()) .nicknameChanged(checkMember.getNicknameChange()) @@ -80,7 +80,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN ApiResponse apiResponse = ApiResponse.builder() .check(false) - .information(memberNicknameRes) + .information(memberNicknameDto) .build(); return ResponseEntity.ok(apiResponse); @@ -97,7 +97,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN memberRepository.updateMemberNicknameChange(newNicknameChanged, memberId); - MemberNicknameRes memberNicknameRes = MemberNicknameRes.builder() + MemberNicknameDto memberNicknameDto = MemberNicknameDto.builder() .id(member.getId()) .nickname(produceNicknameRequest.getNickname()) .nicknameChanged(member.getNicknameChange()) @@ -105,7 +105,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN ApiResponse apiResponse = ApiResponse.builder() .check(true) - .information(memberNicknameRes) + .information(memberNicknameDto) .build(); return ResponseEntity.ok(apiResponse); diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailDto.java similarity index 82% rename from src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java rename to src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailDto.java index 3011e08f..6bb17ec0 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberDetailDto.java @@ -11,7 +11,7 @@ @RequiredArgsConstructor @AllArgsConstructor @Builder -public class MemberDetailRes { +public class MemberDetailDto { private Long id; @@ -21,8 +21,8 @@ public class MemberDetailRes { private Boolean isChanged; - public static MemberDetailRes toDto(Member member) { - return MemberDetailRes.builder() + public static MemberDetailDto toDto(Member member) { + return MemberDetailDto.builder() .id(member.getId()) .name(member.getNickname()) .platform(member.getPlatform()) diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameDto.java similarity index 74% rename from src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java rename to src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameDto.java index 30ace72e..56ad65c9 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameRes.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberNicknameDto.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.member.dto.response; -import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.member.domain.Member; import lombok.AllArgsConstructor; import lombok.Builder; @@ -11,15 +10,15 @@ @RequiredArgsConstructor @AllArgsConstructor @Builder -public class MemberNicknameRes { +public class MemberNicknameDto { private Long id; private String nickname; private Integer nicknameChanged; - public static MemberNicknameRes toDto(Member member) { - return MemberNicknameRes.builder() + public static MemberNicknameDto toDto(Member member) { + return MemberNicknameDto.builder() .id(member.getId()) .nickname(member.getNickname()) .nicknameChanged(member.getNicknameChange()) diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java new file mode 100644 index 00000000..368166d6 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java @@ -0,0 +1,25 @@ +package com.ttubeog.domain.member.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +public class MemberPlaceDto { + @Schema(description = "산책 스팟 ID", defaultValue = "1") + private Long id; + + @Schema(description = "산책 스팟 이름", defaultValue = "나의 산책 스팟") + private String name; + + @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") + private String info; + + @Schema(description = "이미지 리스트") + private List image; +} diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 5bfc8870..f7887bc7 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -4,13 +4,12 @@ import com.ttubeog.domain.auth.dto.response.OAuthTokenResponse; import com.ttubeog.domain.member.application.MemberService; import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; -import com.ttubeog.domain.member.dto.response.MemberDetailRes; -import com.ttubeog.domain.member.dto.response.MemberNicknameRes; +import com.ttubeog.domain.member.dto.response.MemberDetailDto; +import com.ttubeog.domain.member.dto.response.MemberNicknameDto; +import com.ttubeog.domain.member.dto.response.MemberPlaceDto; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.spot.dto.response.SpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.domain.spot.exception.InvalidDongAreaException; -import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; @@ -26,10 +25,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; @Tag(name = "Member", description = "Member API") @RestController @@ -41,7 +38,7 @@ public class MemberController { @Operation(summary = "멤버 정보 확인", description = "현재 접속된 멤버 정보를 확인합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailRes.class))}), + @ApiResponse(responseCode = "200", description = "멤버 확인 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberDetailDto.class))}), @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("") @@ -54,7 +51,7 @@ public ResponseEntity getCurrentMember( @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.닉네임을 이미 변경한 유저는 isChanged == true로 반환되며, 닉네임이 업데이트 되지 않습니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberNicknameRes.class))}), + @ApiResponse(responseCode = "200", description = "닉네임 설정", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = MemberNicknameDto.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname") @@ -131,7 +128,7 @@ public ResponseEntity logout( /** * 내 산책로 조회 API - * @param request 유저 검증 + * @param request 멤버 검증 * @return ResponseEntity -> SpotResponseDto * @throws JsonProcessingException */ @@ -143,7 +140,7 @@ public ResponseEntity logout( content = { @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + array = @ArraySchema(schema = @Schema(implementation = MemberPlaceDto.class)) ) } ), From 5df95a722113b707210457aac2fa30d4ec79bcec Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sat, 17 Feb 2024 20:19:49 +0900 Subject: [PATCH 294/356] =?UTF-8?q?[Refac]=20Spot=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20dongArea=20String=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/spot/application/SpotService.java | 18 +++--------------- .../com/ttubeog/domain/spot/domain/Spot.java | 9 ++++----- .../spot/dto/request/CreateSpotRequestDto.java | 2 +- .../spot/dto/request/UpdateSpotRequestDto.java | 2 +- .../spot/dto/response/SpotResponseDto.java | 2 +- 5 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 1d654fcc..012569ea 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,9 +1,6 @@ package com.ttubeog.domain.spot.application; -import com.ttubeog.domain.area.domain.DongArea; -import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.guestbook.application.GuestBookService; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; @@ -21,7 +18,6 @@ import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; import com.ttubeog.domain.spot.dto.response.SpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; -import com.ttubeog.domain.spot.exception.InvalidDongAreaException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.global.payload.ApiResponse; @@ -44,10 +40,8 @@ public class SpotService { private final SpotRepository spotRepository; private final MemberRepository memberRepository; - private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; private final GuestBookRepository guestBookRepository; - private final GuestBookService guestBookService; private final ImageService imageService; @@ -59,7 +53,7 @@ private ResponseEntity getResponseEntity(Spot spot) { SpotResponseDto createSpotResponseDto = SpotResponseDto.builder() .id(spot.getId()) .memberId(spot.getMember().getId()) - .dongAreaId(spot.getDongArea().getId()) + .dongAreaId(spot.getDongArea()) .detailAddress(spot.getDetailAddress()) .name(spot.getName()) .info(spot.getInfo()) @@ -90,9 +84,6 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques throw new AlreadyExistsSpotException(); } - // 지역코드가 유효한지 체크 - DongArea dongArea = dongAreaRepository.findById(createSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); - // 산책 스팟 이미지가 1~10개 사이인지 체크 if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { throw new InvalidImageListSizeException(); @@ -101,7 +92,7 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques // 산책 스팟 저장 Spot spot = Spot.builder() .member(member) - .dongArea(dongArea) + .dongArea(createSpotRequestDto.getDongAreaId()) .detailAddress(createSpotRequestDto.getDetailAddress()) .name(createSpotRequestDto.getName()) .info(createSpotRequestDto.getInfo()) @@ -161,15 +152,12 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd } } - // 수정하려는 지역코드가 유효한지 체크 - DongArea dongArea = dongAreaRepository.findById(updateSpotRequestDto.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); - // 수정하려는 산책 스팟 이미지가 1~10개 사이인지 체크 if (updateSpotRequestDto.getImage().isEmpty() || updateSpotRequestDto.getImage().size() > 10) { throw new InvalidImageListSizeException(); } - spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), dongArea, updateSpotRequestDto.getDetailAddress()); + spot.updateSpot(updateSpotRequestDto.getName(), updateSpotRequestDto.getInfo(), updateSpotRequestDto.getLatitude(), updateSpotRequestDto.getLongitude(), updateSpotRequestDto.getDongAreaId(), updateSpotRequestDto.getDetailAddress()); spotRepository.save(spot); diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 9410b862..3b0fa1aa 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -53,15 +53,14 @@ public class Spot extends BaseEntity { private Member member; @Schema(description = "지역 코드", example = "DongArea Entity") - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "dong_area_id", nullable = false) - private DongArea dongArea; + @Column(name = "dong_area_id", nullable = false) + private String dongArea; @Schema(description = "상세 주소", example = "301호") @Column(name = "detail_address", nullable = false) private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, DongArea dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, String dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; @@ -73,7 +72,7 @@ public Spot(Long id, String name, String info, Float latitude, Float longitude, this.detailAddress = detailAddress; } - public void updateSpot(String name, String info, Float latitude, Float longitude, DongArea dongArea, String detailAddress) { + public void updateSpot(String name, String info, Float latitude, Float longitude, String dongArea, String detailAddress) { this.name = name; this.info = info; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 4b4089de..148fcea5 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -17,7 +17,7 @@ public class CreateSpotRequestDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 84debe42..0ffac459 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -16,7 +16,7 @@ public class UpdateSpotRequestDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 794d5d01..64ae4c4c 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -21,7 +21,7 @@ public class SpotResponseDto { private String name; @Schema(description = "지역 코드 ID", defaultValue = "1") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소", defaultValue = "1층") private String detailAddress; From 5353858226e63c027d69640c89437f9513f735d0 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sat, 17 Feb 2024 20:36:56 +0900 Subject: [PATCH 295/356] =?UTF-8?q?[Update]=20Store=20Entity=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/store/application/StoreService.java | 7 +++---- src/main/java/com/ttubeog/domain/store/domain/Store.java | 5 ++--- .../ttubeog/domain/store/dto/request/RegisterStoreReq.java | 2 +- .../domain/store/dto/response/GetStoreDetailRes.java | 4 ++-- .../domain/store/dto/response/RegisterStoreRes.java | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 4a919c01..1e71e250 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -67,7 +67,6 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - DongArea dongArea = dongAreaRepository.findById(registerStoreReq.getDongAreaId()).orElseThrow(InvalidDongAreaException::new); if (registerStoreReq.getImage().isEmpty() || registerStoreReq.getImage().size() > 10) { throw new InvalidImageListSizeException(); @@ -76,7 +75,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore Store store = Store.builder() .name(registerStoreReq.getName()) .info(registerStoreReq.getInfo()) - .dongArea(dongArea) + .dongArea(registerStoreReq.getDongAreaId()) .member(member) .detailAddress(registerStoreReq.getDetailAddress()) .latitude(registerStoreReq.getLatitude()) @@ -103,7 +102,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .memberId(member.getId()) .name(store.getName()) .info(store.getInfo()) - .dongAreaId(store.getDongArea().getId()) + .dongAreaId(store.getDongArea()) .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) @@ -254,7 +253,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .memberId(store.getMember().getId()) .name(store.getName()) .info(store.getInfo()) - .dongAreaId(store.getDongArea().getId()) + .dongAreaId(store.getDongArea()) .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 930e0ddc..32d6061a 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -45,9 +45,8 @@ public class Store extends BaseEntity { @Enumerated(EnumType.STRING) private StoreType type; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "dong_area_id") - private DongArea dongArea; + @Column(name = "dong_area_id") + private String dongArea; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") diff --git a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java index a238766a..6040b408 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java +++ b/src/main/java/com/ttubeog/domain/store/dto/request/RegisterStoreReq.java @@ -17,7 +17,7 @@ public class RegisterStoreReq { private String info; @Schema(description = "지역(동) ID") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소") private String detailAddress; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index 834a4384..71eec7dd 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -26,7 +26,7 @@ public class GetStoreDetailRes { private String info; @Schema(description = "지역(동) ID") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소") private String detailAddress; @@ -59,7 +59,7 @@ public class GetStoreDetailRes { private Boolean isFavorited; @Builder - public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, + public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, String dongAreaId, String detailAddress, Double latitude, Double longitude, List image, Float stars, StoreType type, List storeBenefits, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { this.storeId = storeId; diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java index c8222f49..ac8a7f0e 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/RegisterStoreRes.java @@ -24,7 +24,7 @@ public class RegisterStoreRes { private String info; @Schema(description = "지역(동) ID") - private Long dongAreaId; + private String dongAreaId; @Schema(description = "상세 주소") private String detailAddress; @@ -45,7 +45,7 @@ public class RegisterStoreRes { private StoreType type; @Builder - public RegisterStoreRes(Long storeId, Long memberId, String name, String info, Long dongAreaId, + public RegisterStoreRes(Long storeId, Long memberId, String name, String info, String dongAreaId, String detailAddress, Double latitude, Double longitude, List image, Float stars, StoreType type) { this.storeId = storeId; this.memberId = memberId; From 1417d2ccffc1821ebd0c088a2fb17f76827fb161 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sat, 17 Feb 2024 21:03:34 +0900 Subject: [PATCH 296/356] =?UTF-8?q?[Update]=20PlaceService=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/place/application/PlaceService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 91863493..8b334c19 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -106,7 +106,7 @@ private GetAllPlaceRes mapStoreToDto(HttpServletRequest request, Store store) { return GetAllPlaceRes.builder() .placeId(store.getId()) .placeType(placeType) - .dongName(store.getDongArea().getDongName()) + .dongName(store.getDongArea()) .memberId(store.getMember().getId()) .name(store.getName()) .info(store.getInfo()) From 62bf50c575d6b0da544b39d185a74201ef9a8ce5 Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 18 Feb 2024 00:27:06 +0900 Subject: [PATCH 297/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=EC=82=B0=EC=B1=85?= =?UTF-8?q?=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84=20(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 25 +++++++++++++++++ .../domain/repository/MemberRepository.java | 5 +++- .../member/dto/response/MemberPlaceDto.java | 2 +- .../member/presentation/MemberController.java | 27 +++---------------- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 23596d4c..f7e57bc1 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -11,9 +11,11 @@ import com.ttubeog.domain.member.dto.request.ProduceNicknameRequest; import com.ttubeog.domain.member.dto.response.MemberDetailDto; import com.ttubeog.domain.member.dto.response.MemberNicknameDto; +import com.ttubeog.domain.member.dto.response.MemberPlaceDto; import com.ttubeog.domain.member.exception.FailureMemberDeleteException; import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; @@ -26,6 +28,7 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @RequiredArgsConstructor @Service @@ -231,4 +234,26 @@ public ResponseEntity deleteInactiveMember() { throw new FailureMemberDeleteException(); } } + + @Transactional + public ResponseEntity getMySpotList(HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberId(request); + + List spotsByMemberId = memberRepository.findSpotsByMemberId(memberId); + + List memberPlaceDtoList = spotsByMemberId.stream() + .map(spot -> MemberPlaceDto.builder() + .id(spot.getId()) + .name(spot.getName()) + .info(spot.getInfo()) + .build()) + .collect(Collectors.toList()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(memberPlaceDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 6eddef82..72106da4 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -3,6 +3,7 @@ import com.ttubeog.domain.auth.domain.Platform; import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; +import com.ttubeog.domain.spot.domain.Spot; import io.lettuce.core.dynamic.annotation.Param; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; @@ -24,7 +25,6 @@ public interface MemberRepository extends JpaRepository{ List findByStatus(Status status); - Optional findByPlatformAndPlatformId(Platform platform, String platformId); Optional findByRefreshToken(String refreshToken); @@ -45,4 +45,7 @@ public interface MemberRepository extends JpaRepository{ Boolean existsByNickname(String nickname); + @Modifying + @Query("SELECT s FROM Spot s WHERE s.member.id = :memberId") + List findSpotsByMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java index 368166d6..66164177 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java @@ -21,5 +21,5 @@ public class MemberPlaceDto { private String info; @Schema(description = "이미지 리스트") - private List image; + private String image; } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index f7887bc7..bfe182e0 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -154,33 +154,12 @@ public ResponseEntity logout( ) } ), - @ApiResponse( - responseCode = "500 - AlreadyExistsSpotException", - description = "이미 존재하는 산책 장소명입니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = AlreadyExistsSpotException.class)) - ) - } - ), - @ApiResponse( - responseCode = "500 - InvalidDongAreaException", - description = "유효하지 않은 지역 정보입니다.", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = InvalidDongAreaException.class)) - ) - } - ), } ) - @GetMapping("/{memberId}/spot") + @GetMapping("/spot") public ResponseEntity getMySpotList( - @CurrentUser HttpServletRequest request, - @RequestParam(name = "memberId") Long memberId + @CurrentUser HttpServletRequest request ) throws JsonProcessingException { - return null; + return memberService.getMySpotList(request); } } From 210874a1d1bd584bab49d847a44c702c5e3418c5 Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 18 Feb 2024 00:45:48 +0900 Subject: [PATCH 298/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=EB=A7=A4=EC=9E=A5?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 25 +++++++- .../domain/repository/MemberRepository.java | 7 ++- .../member/dto/response/MemberPlaceDto.java | 4 +- .../member/presentation/MemberController.java | 61 ++++++++++++++++--- 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index f7e57bc1..3d716085 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -16,6 +16,7 @@ import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; @@ -239,7 +240,7 @@ public ResponseEntity deleteInactiveMember() { public ResponseEntity getMySpotList(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); - List spotsByMemberId = memberRepository.findSpotsByMemberId(memberId); + List spotsByMemberId = memberRepository.findSpotByMemberId(memberId); List memberPlaceDtoList = spotsByMemberId.stream() .map(spot -> MemberPlaceDto.builder() @@ -256,4 +257,26 @@ public ResponseEntity getMySpotList(HttpServletRequest request) { return ResponseEntity.ok(apiResponse); } + + @Transactional + public ResponseEntity getMyStoreList(HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberId(request); + + List spotsByMemberId = memberRepository.findStoreByMemberId(memberId); + + List memberPlaceDtoList = spotsByMemberId.stream() + .map(store -> MemberPlaceDto.builder() + .id(store.getId()) + .name(store.getName()) + .info(store.getInfo()) + .build()) + .collect(Collectors.toList()); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(memberPlaceDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java index 72106da4..47546334 100644 --- a/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/ttubeog/domain/member/domain/repository/MemberRepository.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.auth.domain.Status; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import io.lettuce.core.dynamic.annotation.Param; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; @@ -47,5 +48,9 @@ public interface MemberRepository extends JpaRepository{ @Modifying @Query("SELECT s FROM Spot s WHERE s.member.id = :memberId") - List findSpotsByMemberId(@Param("memberId") Long memberId); + List findSpotByMemberId(@Param("memberId") Long memberId); + + @Modifying + @Query("SELECT s FROM Store s WHERE s.member.id = :memberId") + List findStoreByMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java index 66164177..4871fff8 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java @@ -11,10 +11,10 @@ @Builder @AllArgsConstructor public class MemberPlaceDto { - @Schema(description = "산책 스팟 ID", defaultValue = "1") + @Schema(description = "장소 ID", defaultValue = "1") private Long id; - @Schema(description = "산책 스팟 이름", defaultValue = "나의 산책 스팟") + @Schema(description = "장소 이름", defaultValue = "나의 산책 스팟") private String name; @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index bfe182e0..e902d7de 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -128,22 +128,24 @@ public ResponseEntity logout( /** * 내 산책로 조회 API + * * @param request 멤버 검증 * @return ResponseEntity -> SpotResponseDto * @throws JsonProcessingException */ @Operation(summary = "내 산책 스팟 조회 API", description = "내가 등록한 산책 스팟을 조회합니다.\n", - responses = {@ApiResponse( - responseCode = "200", - description = "OK", - content = { - @Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = MemberPlaceDto.class)) - ) - } - ), + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = MemberPlaceDto.class)) + ) + } + ), @ApiResponse( responseCode = "500 - InvalidMemberException", description = "멤버가 올바르지 않습니다.", @@ -162,4 +164,43 @@ public ResponseEntity getMySpotList( ) throws JsonProcessingException { return memberService.getMySpotList(request); } + + /** + * 내 매장 조회 API + * + * @param request 멤버 검증 + * @return ResponseEntity -> SpotResponseDto + * @throws JsonProcessingException + */ + @Operation(summary = "내 매장 조회 API", + description = "내가 등록한 매장을 조회합니다.\n", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = MemberPlaceDto.class)) + ) + } + ), + @ApiResponse( + responseCode = "500 - InvalidMemberException", + description = "멤버가 올바르지 않습니다.", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = InvalidMemberException.class)) + ) + } + ), + } + ) + @GetMapping("/store") + public ResponseEntity getMyStoreList( + @CurrentUser HttpServletRequest request + ) throws JsonProcessingException { + return memberService.getMyStoreList(request); + } } From eb4056ecb8f54a53684587d9d25d20a4431f49ed Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 18 Feb 2024 00:46:03 +0900 Subject: [PATCH 299/356] =?UTF-8?q?[Fix]=20startIndex=EA=B0=80=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=81=AC=EA=B8=B0=EB=A5=BC=20=EC=B4=88?= =?UTF-8?q?=EA=B3=BC=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/place/application/PlaceService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 8b334c19..c848c739 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -56,6 +56,7 @@ public class PlaceService { public List getPageOfPlaces(List places, int page, int size) { int startIndex = page * size; + startIndex = Math.min(startIndex, places.size()); int endIndex = Math.min(startIndex + size, places.size()); return places.subList(startIndex, endIndex); From f8724f13e1b7f7f99a124214c6429c0bf9f3731c Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 18 Feb 2024 01:51:06 +0900 Subject: [PATCH 300/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=EB=A7=A4=EC=9E=A5?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=ED=8E=98=EC=9D=B4=EC=A7=95=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20(#73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 26 +++++++++++++------ .../member/presentation/MemberController.java | 10 +++---- .../domain/repository/StoreRepository.java | 4 +++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 3d716085..33994228 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -17,16 +17,20 @@ import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.DefaultAssert; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -39,6 +43,7 @@ public class MemberService { private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenService refreshTokenService; private final RedisTemplate redisTemplate; + private final StoreRepository storeRepository; private static final int WAITING_PERIOD_DAYS = 3; @@ -259,18 +264,23 @@ public ResponseEntity getMySpotList(HttpServletRequest request) { } @Transactional - public ResponseEntity getMyStoreList(HttpServletRequest request) { + public ResponseEntity getMyStoreList(HttpServletRequest request, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); List spotsByMemberId = memberRepository.findStoreByMemberId(memberId); - List memberPlaceDtoList = spotsByMemberId.stream() - .map(store -> MemberPlaceDto.builder() - .id(store.getId()) - .name(store.getName()) - .info(store.getInfo()) - .build()) - .collect(Collectors.toList()); + Page storePage = storeRepository.findAllByMemberId(memberId, PageRequest.of(pageNum, 10)); + + List memberPlaceDtoList = new ArrayList<>(); + + for (Store store : storePage) { + MemberPlaceDto memberPlaceDto = MemberPlaceDto.builder() + .id(store.getId()) + .name(store.getName()) + .info(store.getInfo()) + .build(); + memberPlaceDtoList.add(memberPlaceDto); + } ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index e902d7de..1b201a2c 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -8,8 +8,6 @@ import com.ttubeog.domain.member.dto.response.MemberNicknameDto; import com.ttubeog.domain.member.dto.response.MemberPlaceDto; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; -import com.ttubeog.domain.spot.exception.InvalidDongAreaException; import com.ttubeog.global.config.security.token.CurrentUser; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; @@ -169,6 +167,7 @@ public ResponseEntity getMySpotList( * 내 매장 조회 API * * @param request 멤버 검증 + * @param pageNum * @return ResponseEntity -> SpotResponseDto * @throws JsonProcessingException */ @@ -197,10 +196,11 @@ public ResponseEntity getMySpotList( ), } ) - @GetMapping("/store") + @GetMapping("/store&{pageNum}") public ResponseEntity getMyStoreList( - @CurrentUser HttpServletRequest request + @CurrentUser HttpServletRequest request, + @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return memberService.getMyStoreList(request); + return memberService.getMyStoreList(request, pageNum); } } diff --git a/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java b/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java index d5ff3456..a5f2f9b1 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java +++ b/src/main/java/com/ttubeog/domain/store/domain/repository/StoreRepository.java @@ -2,6 +2,8 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.store.domain.Store; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,4 +13,6 @@ public interface StoreRepository extends JpaRepository { Optional findByIdAndMember(Long id, Member member); + + Page findAllByMemberId(Long memberId, PageRequest pageRequest); } From 95a91de7716082272148cf7a510d42ef09dff33e Mon Sep 17 00:00:00 2001 From: arinming Date: Sun, 18 Feb 2024 01:59:55 +0900 Subject: [PATCH 301/356] =?UTF-8?q?[Feat]=20=EB=82=B4=20=EC=82=B0=EC=B1=85?= =?UTF-8?q?=20=EC=8A=A4=ED=8C=9F=20=EC=A1=B0=ED=9A=8C=20API=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=95=20=EC=B2=98=EB=A6=AC=20(#73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 23 +++++++++++-------- .../member/dto/response/MemberPlaceDto.java | 2 +- .../member/presentation/MemberController.java | 8 ++++--- .../domain/repository/SpotRepository.java | 5 +++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 33994228..cb7489fd 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -16,6 +16,7 @@ import com.ttubeog.domain.member.exception.InvalidAccessTokenExpiredException; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.DefaultAssert; @@ -44,6 +45,7 @@ public class MemberService { private final RefreshTokenService refreshTokenService; private final RedisTemplate redisTemplate; private final StoreRepository storeRepository; + private final SpotRepository spotRepository; private static final int WAITING_PERIOD_DAYS = 3; @@ -242,18 +244,21 @@ public ResponseEntity deleteInactiveMember() { } @Transactional - public ResponseEntity getMySpotList(HttpServletRequest request) { + public ResponseEntity getMySpotList(HttpServletRequest request, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); - List spotsByMemberId = memberRepository.findSpotByMemberId(memberId); + Page spotPage = spotRepository.findAllByMemberId(memberId, PageRequest.of(pageNum, 10)); - List memberPlaceDtoList = spotsByMemberId.stream() - .map(spot -> MemberPlaceDto.builder() - .id(spot.getId()) - .name(spot.getName()) - .info(spot.getInfo()) - .build()) - .collect(Collectors.toList()); + List memberPlaceDtoList = new ArrayList<>(); + + for (Spot spot : spotPage) { + MemberPlaceDto memberPlaceDto = MemberPlaceDto.builder() + .id(spot.getId()) + .name(spot.getName()) + .info(spot.getInfo()) + .build(); + memberPlaceDtoList.add(memberPlaceDto); + } ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java index 4871fff8..dd11aa1e 100644 --- a/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java +++ b/src/main/java/com/ttubeog/domain/member/dto/response/MemberPlaceDto.java @@ -17,7 +17,7 @@ public class MemberPlaceDto { @Schema(description = "장소 이름", defaultValue = "나의 산책 스팟") private String name; - @Schema(description = "세부 정보", defaultValue = "연인, 친구들과 산책하기 좋은 장소입니다.") + @Schema(description = "세부 정보", defaultValue = "내 장소의 세부 정보") private String info; @Schema(description = "이미지 리스트") diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 1b201a2c..7ac0ecf0 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -128,6 +128,7 @@ public ResponseEntity logout( * 내 산책로 조회 API * * @param request 멤버 검증 + * @param pageNum * @return ResponseEntity -> SpotResponseDto * @throws JsonProcessingException */ @@ -156,11 +157,12 @@ public ResponseEntity logout( ), } ) - @GetMapping("/spot") + @GetMapping("/spot&{pageNum}") public ResponseEntity getMySpotList( - @CurrentUser HttpServletRequest request + @CurrentUser HttpServletRequest request, + @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return memberService.getMySpotList(request); + return memberService.getMySpotList(request, pageNum); } /** diff --git a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java index c2022844..8b47a8c2 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/repository/SpotRepository.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.spot.domain.repository; import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -12,5 +15,5 @@ public interface SpotRepository extends JpaRepository { Optional findByName(String name); - + Page findAllByMemberId(Long memberId, PageRequest pageRequest); } From e41295cf365926b1659c5270742deb7ac726abbb Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sun, 18 Feb 2024 04:03:14 +0900 Subject: [PATCH 302/356] [Docs] edit gradle.yml --- .github/workflows/gradle.yml | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 04e3f9de..5ba6b077 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -44,31 +44,18 @@ jobs: - name: Copy secret env: OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} - OCCUPY_DB_SECRET: ${{ secrets.OCCUPY_DB_SECRET }} - OCCUPY_OAUTH_SECRET: ${{ secrets.OCCUPY_OAUTH_SECRET }} OCCUPY_LOGBACK_SECRET: ${{ secrets.OCCUPY_LOGBACK_SECRET }} OCCUPY_SECRET_DIR: ./src/main/resources - OCCUPY_DB_SECRET_DIR: ./src/main/resources/database - OCCUPY_OAUTH_SECRET_DIR: ./src/main/resources/oauth2 OCCUPY_LOGBACK_SECRET_DIR: ./src/main/resources OCCUPY_SECRET_DIR_FILE_NAME: application.yml - OCCUPY_DB_SECRET_DIR_FILE_NAME: application-database.yml - OCCUPY_OAUTH_SECRET_DIR_FILE_NAME: application-oauth2.yml OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback-test.xml run: | - mkdir $OCCUPY_DB_SECRET_DIR - mkdir $OCCUPY_OAUTH_SECRET_DIR - touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - touch $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - touch $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME touch $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME - echo "$OCCUPY_DB_SECRET" > $OCCUPY_DB_SECRET_DIR/$OCCUPY_DB_SECRET_DIR_FILE_NAME - echo "$OCCUPY_OAUTH_SECRET" > $OCCUPY_OAUTH_SECRET_DIR/$OCCUPY_OAUTH_SECRET_DIR_FILE_NAME echo "$OCCUPY_LOGBACK_SECRET" > $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME # gradlew 실행 권한 부여 @@ -88,25 +75,6 @@ jobs: path: | build/libs/*.jar -# - name: Remove past EC2 raw sorce dir -# uses: appleboy/ssh-action@master -# with: -# key: ${{ secrets.EC2_KEY }} -# host: ${{ secrets.EC2_HOST }} -# username: ${{ secrets.EC2_USER }} -# command: sudo rm -rf /home/ubuntu/app/code -# port: 22 - - -# - name: Upload raw sorce to EC2 -# uses: appleboy/scp-action@master -# with: -# key: ${{ secrets.EC2_KEY }} -# host: ${{ secrets.EC2_HOST }} -# username: ${{ secrets.EC2_USER }} -# source: . -# target: "/home/ubuntu/app/code" - - name: Start redis-server uses: appleboy/scp-action@master with: From 8cbed1f307fa23a92cf63662ee58091238a48516 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Sun, 18 Feb 2024 04:08:49 +0900 Subject: [PATCH 303/356] [Docs] Update gradle.yml --- .github/workflows/gradle.yml | 39 ++---------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5ba6b077..2381c5e9 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,10 +1,3 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle - name: Java CI with Gradle on: @@ -84,12 +77,8 @@ jobs: target: /home/ubuntu # specify the target path if needed source: . # specify the source directory or file if needed command: sudo systemctl start redis-server - port: 22 - timeout: 30s - command_timeout: 10m - tar_exec: tar - proxy_port: 22 - proxy_timeout: 30s + + deploy: @@ -98,30 +87,6 @@ jobs: runs-on: ubuntu-22.04 steps: - # (6) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ env.AWS_REGION }} - - # (7) 빌드 결과물을 S3 버킷에 업로드 -# - name: Upload to AWS S3 - # run: | - # aws deploy push \ - # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - # --s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \ - # --source . - - # # (8) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 - # - name: Deploy to AWS EC2 from S3 - # run: | - # aws deploy create-deployment \ - # --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ - # --deployment-config-name CodeDeployDefault.AllAtOnce \ - # --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ - # --s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip - name: Download build artifacts uses: actions/download-artifact@v2 with: From 792125844adb73b8121c3b474fc9147288d1b686 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 18 Feb 2024 04:16:01 +0900 Subject: [PATCH 304/356] =?UTF-8?q?[Refac]=20=EC=9C=84=EB=8F=84,=20?= =?UTF-8?q?=EA=B2=BD=EB=8F=84=20=ED=83=80=EC=9E=85=20Double=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/CommentService.java | 23 ++++++++++--------- .../domain/comment/domain/Comment.java | 4 ++-- .../comment/dto/request/GetCommentReq.java | 5 ++-- .../comment/dto/request/WriteCommentReq.java | 6 +++-- .../comment/dto/response/WriteCommentRes.java | 6 ++--- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 276b17d4..ff48c1b8 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -75,7 +75,7 @@ public ResponseEntity updateComment(HttpServletRequest request, UpdateComment Comment comment = commentRepository.findById(updateCommentReq.getCommentId()).orElseThrow(NonExistentCommentException::new); Member commentWriter = comment.getMember(); - if (commentWriter.getId() != member.getId()) { + if (commentWriter.getId() != memberId) { throw new UnauthorizedMemberException(); } @@ -118,8 +118,8 @@ public List getAllComments() { // AR뷰를 위한 댓글 조회 public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { - Float userLatitude = getCommentReq.getLatitude(); - Float userLongitude = getCommentReq.getLongitude(); + Double userLatitude = getCommentReq.getLatitude(); + Double userLongitude = getCommentReq.getLongitude(); List allComments = getAllComments(); Double radius = 20.0; // 반경값 확인 필요 @@ -127,10 +127,10 @@ public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { for (Comment comment : allComments) { - Float commentLatitude = comment.getLatitude(); - Float commentLongitude = comment.getLongitude(); + Double commentLatitude = comment.getLatitude(); + Double commentLongitude = comment.getLongitude(); - double distance = calculateDistance(userLatitude, userLongitude, commentLatitude, commentLongitude); + Double distance = calculateDistance(userLatitude, userLongitude, commentLatitude, commentLongitude); if (distance < radius) { GetCommentRes getCommentRes = GetCommentRes.builder() @@ -153,17 +153,18 @@ public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { } // 거리 계산 - private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + private double calculateDistance(Double lat1, Double lon1, Double lat2, Double lon2) { + double R = 6371; // 지구 반지름 - double dLat = Math.toRadians(lat2 - lat1); - double dLon = Math.toRadians(lon2 - lon1); + Double dLat = Math.toRadians(lat2 - lat1); + Double dLon = Math.toRadians(lon2 - lon1); - double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); - double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 단위 km + Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 단위 km return R * c; } diff --git a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java index 6d4f8c01..2360d223 100644 --- a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java +++ b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java @@ -21,10 +21,10 @@ public class Comment extends BaseEntity { private String content; @Column(name = "latitude") - private Float latitude; + private Double latitude; @Column(name = "longitude") - private Float longitude; + private Double longitude; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java index 5c16e981..2d0dd6f8 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java @@ -7,9 +7,8 @@ public class GetCommentReq { @Schema(description = "사용자 위치 위도값") - private Float latitude; + private Double latitude; @Schema(description = "사용자 위치 경도값") - private Float longitude; - + private Double longitude; } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java index d0541d7f..8e98076d 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java @@ -9,8 +9,10 @@ public class WriteCommentReq { @Schema(description = "댓글 내용") private String content; + @Schema(description = "위도") - private Float latitude; + private Double latitude; + @Schema(description = "경도") - private Float longitude; + private Double longitude; } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java index a3b78a19..546aaa7e 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java @@ -17,13 +17,13 @@ public class WriteCommentRes { private String content; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Builder - public WriteCommentRes(Long commentId, Long memberId, String content, Float latitude, Float longitude) { + public WriteCommentRes(Long commentId, Long memberId, String content, Double latitude, Double longitude) { this.commentId = commentId; this.memberId = memberId; this.content = content; From b891a168d90e08ab752020b76e8167e8444b8902 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sun, 18 Feb 2024 04:25:27 +0900 Subject: [PATCH 305/356] [Chore] edit class path --- src/main/java/com/ttubeog/TtubeogApplication.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/ttubeog/TtubeogApplication.java b/src/main/java/com/ttubeog/TtubeogApplication.java index 414bf6f4..653546ed 100644 --- a/src/main/java/com/ttubeog/TtubeogApplication.java +++ b/src/main/java/com/ttubeog/TtubeogApplication.java @@ -8,9 +8,6 @@ @SpringBootApplication @EnableScheduling -@PropertySource(value = {"classpath:database/application-database.yml"}, factory = YamlPropertySourceFactory.class) -@PropertySource(value = { "classpath:oauth2/application-oauth2.yml" }, factory = YamlPropertySourceFactory.class) -@PropertySource(value = { "classpath:swagger/application-springdoc.yml" }, factory = YamlPropertySourceFactory.class) public class TtubeogApplication { public static void main(String[] args) { From a3d416a70883e6f96748d47a3db8914db248cf28 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Sun, 18 Feb 2024 04:35:26 +0900 Subject: [PATCH 306/356] Update gradle.yml --- .github/workflows/gradle.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2381c5e9..9f1f0c07 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -74,8 +74,7 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} - target: /home/ubuntu # specify the target path if needed - source: . # specify the source directory or file if needed + target: /home/ubuntu command: sudo systemctl start redis-server From 1d8394aabdbf3dece1bd2568ded75d1d7b563d53 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Sun, 18 Feb 2024 04:37:57 +0900 Subject: [PATCH 307/356] Update gradle.yml --- .github/workflows/gradle.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9f1f0c07..9bd77c41 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -74,7 +74,8 @@ jobs: key: ${{ secrets.EC2_KEY }} host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} - target: /home/ubuntu + target: /home/ubuntu/app/spring_source + source: . command: sudo systemctl start redis-server From 4cbc5ebd2703dd5aa8e3f4877d45eb828d834bc0 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sun, 18 Feb 2024 05:25:33 +0900 Subject: [PATCH 308/356] =?UTF-8?q?[Refac]=20Spot=20=EC=9C=84=EB=8F=84,=20?= =?UTF-8?q?=EA=B2=BD=EB=8F=84=20=ED=83=80=EC=9E=85=20Double=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/place/application/PlaceService.java | 5 ++--- src/main/java/com/ttubeog/domain/spot/domain/Spot.java | 8 ++++---- .../domain/spot/dto/request/CreateSpotRequestDto.java | 4 ++-- .../domain/spot/dto/request/UpdateSpotRequestDto.java | 4 ++-- .../ttubeog/domain/spot/dto/response/SpotResponseDto.java | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index c848c739..89f712b4 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -151,9 +151,8 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { .memberId(spot.getMember().getId()) .name(spot.getName()) .info(spot.getInfo()) - // 위도, 경도 double로 변경 필요 - //.latitude(spot.getLatitude()) - //.longitude(spot.getLongitude()) + .latitude(spot.getLatitude()) + .longitude(spot.getLongitude()) .image(representativeImageUrl) .stars(spot.getStars()) .guestbookCount(intValue(guestBookRepository.countAllBySpot(spot))) diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 3b0fa1aa..eb178317 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -37,11 +37,11 @@ public class Spot extends BaseEntity { @Schema(description = "위도", example = "36.5642886") @Column(name = "latitude", nullable = false) - private Float latitude; + private Double latitude; @Schema(description = "경도", example = "126.9275718") @Column(name = "longitude", nullable = false) - private Float longitude; + private Double longitude; @Schema(description = "별점 평균", example = "3.4") @Column(name = "stars") @@ -60,7 +60,7 @@ public class Spot extends BaseEntity { @Column(name = "detail_address", nullable = false) private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, String dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Double latitude, Double longitude, Float stars, Member member, String dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; @@ -72,7 +72,7 @@ public Spot(Long id, String name, String info, Float latitude, Float longitude, this.detailAddress = detailAddress; } - public void updateSpot(String name, String info, Float latitude, Float longitude, String dongArea, String detailAddress) { + public void updateSpot(String name, String info, Double latitude, Double longitude, String dongArea, String detailAddress) { this.name = name; this.info = info; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 148fcea5..e8ada49c 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -26,10 +26,10 @@ public class CreateSpotRequestDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 0ffac459..f7751985 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -25,10 +25,10 @@ public class UpdateSpotRequestDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 64ae4c4c..086a8030 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -33,10 +33,10 @@ public class SpotResponseDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; From 1908c2347ab884b508121cbaed75fe4f7e8f438c Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 16:45:21 +0900 Subject: [PATCH 309/356] =?UTF-8?q?[Chore]=20GuestBook=EC=97=90=20memberNa?= =?UTF-8?q?me=20=EC=B6=94=EA=B0=80=20=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리스트 반환하는 방법도 수정했습니다. --- .../application/GuestBookService.java | 51 +++++++++---------- .../dto/response/GuestBookResponseDto.java | 5 +- .../swagger/application-springdoc.yml | 14 ----- 3 files changed, 29 insertions(+), 41 deletions(-) delete mode 100644 src/main/resources/swagger/application-springdoc.yml diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 5f485e4c..c84d5120 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -35,6 +35,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; @RequiredArgsConstructor @@ -66,6 +67,7 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { .guestBookType(guestBook.getGuestBookType()) .spotId(guestBook.getSpot().getId()) .memberId(guestBook.getMember().getId()) + .memberName(guestBook.getMember().getNickname()) .star(guestBook.getStar()) .build(); } else if (guestBook.getGuestBookType().equals(GuestBookType.STORE)) { @@ -75,6 +77,7 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { .guestBookType(guestBook.getGuestBookType()) .storeId(guestBook.getStore().getId()) .memberId(guestBook.getMember().getId()) + .memberName(guestBook.getMember().getNickname()) .star(guestBook.getStar()) .build(); } else { @@ -195,19 +198,17 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long Page guestBookPage = guestBookRepository.findAllBySpot(spot, PageRequest.of(pageNum, 10)); - List guestBookResponseDtoList = null; - - for (GuestBook guestBook : guestBookPage) { - GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() - .id(guestBook.getId()) - .content(guestBook.getContent()) - .guestBookType(guestBook.getGuestBookType()) - .spotId(guestBook.getSpot().getId()) - .memberId(guestBook.getMember().getId()) - .star(guestBook.getStar()) - .build(); - guestBookResponseDtoList.add(guestBookResponseDto); - } + List guestBookResponseDtoList = guestBookPage.stream().map( + guestBook -> GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .spotId(guestBook.getSpot().getId()) + .memberId(guestBook.getMember().getId()) + .memberName(guestBook.getMember().getNickname()) + .star(guestBook.getStar()) + .build() + ).toList(); ApiResponse apiResponse = ApiResponse.builder() .check(true) @@ -227,19 +228,17 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long Page guestBookPage = guestBookRepository.findAllByStore(store, PageRequest.of(pageNum, 10)); - List guestBookResponseDtoList = null; - - for (GuestBook guestBook : guestBookPage) { - GuestBookResponseDto guestBookResponseDto = GuestBookResponseDto.builder() - .id(guestBook.getId()) - .content(guestBook.getContent()) - .guestBookType(guestBook.getGuestBookType()) - .spotId(guestBook.getSpot().getId()) - .memberId(guestBook.getMember().getId()) - .star(guestBook.getStar()) - .build(); - guestBookResponseDtoList.add(guestBookResponseDto); - } + List guestBookResponseDtoList = guestBookPage.stream().map( + guestBook -> GuestBookResponseDto.builder() + .id(guestBook.getId()) + .content(guestBook.getContent()) + .guestBookType(guestBook.getGuestBookType()) + .storeId(guestBook.getStore().getId()) + .memberId(guestBook.getMember().getId()) + .memberName(guestBook.getMember().getNickname()) + .star(guestBook.getStar()) + .build() + ).toList(); ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java index 1643090a..dbdb41d1 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/response/GuestBookResponseDto.java @@ -14,6 +14,8 @@ public class GuestBookResponseDto { private Long memberId; + private String memberName; + private GuestBookType guestBookType; private Long spotId; @@ -24,9 +26,10 @@ public class GuestBookResponseDto { private Float star; - public GuestBookResponseDto(Long id, Long memberId, GuestBookType guestBookType, Long spotId, Long storeId, String content, Float star) { + public GuestBookResponseDto(Long id, Long memberId, String memberName, GuestBookType guestBookType, Long spotId, Long storeId, String content, Float star) { this.id = id; this.memberId = memberId; + this.memberName = memberName; this.guestBookType = guestBookType; this.spotId = spotId; this.storeId = storeId; diff --git a/src/main/resources/swagger/application-springdoc.yml b/src/main/resources/swagger/application-springdoc.yml deleted file mode 100644 index 59bfb544..00000000 --- a/src/main/resources/swagger/application-springdoc.yml +++ /dev/null @@ -1,14 +0,0 @@ -springdoc: - default-consumes-media-type: application/json;charset=UTF-8 - default-produces-media-type: application/json;charset=UTF-8 - swagger-ui: - path: swagger - disable-swagger-default-url: true - display-request-duration: true - operations-sorter: method - doc-expansion: none - - # enabled: false - # query-config-enabled: false - # api-docs: - # enabled: false \ No newline at end of file From 51c11b19ab87a9cace4a07c5c55ad9351c763642 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 18:42:26 +0900 Subject: [PATCH 310/356] =?UTF-8?q?[Chore]=20=EC=8A=A4=ED=8C=9F=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 좋아요 수, 방명록 수 등 추가 --- .../domain/spot/application/SpotService.java | 44 ++++++++++-- .../com/ttubeog/domain/spot/domain/Spot.java | 8 +-- .../dto/request/CreateSpotRequestDto.java | 4 +- .../dto/request/UpdateSpotRequestDto.java | 4 +- .../spot/dto/response/GetSpotDetailRes.java | 71 +++++++++++++++++++ .../spot/dto/response/SpotResponseDto.java | 4 +- 6 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 012569ea..02a6c338 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.spot.application; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.benefit.domain.Benefit; +import com.ttubeog.domain.benefit.domain.BenefitType; +import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; @@ -8,6 +11,7 @@ import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; +import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -16,10 +20,14 @@ import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.domain.spot.dto.response.GetSpotDetailRes; import com.ttubeog.domain.spot.dto.response.SpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.Store; +import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; +import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; @@ -30,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.stream.Collectors; import static com.ttubeog.domain.image.application.ImageService.getImageString; @@ -42,6 +51,8 @@ public class SpotService { private final MemberRepository memberRepository; private final ImageRepository imageRepository; private final GuestBookRepository guestBookRepository; + private final LikesRepository likesRepository; + private final BenefitRepository benefitRepository; private final ImageService imageService; @@ -71,6 +82,7 @@ private ResponseEntity getResponseEntity(Spot spot) { return ResponseEntity.ok(apiResponse); } + //Spot 생성 Method @Transactional public ResponseEntity createSpot(HttpServletRequest request, CreateSpotRequestDto createSpotRequestDto) { @@ -117,16 +129,39 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques return getResponseEntity(spot); } + //ID로 스팟 조회 Method public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); + Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Spot spot = spotRepository.findById(spotId).orElseThrow(NonExistentStoreException::new); - // 유효한 사용자 로그인 상태인지 체크 - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + Integer guestbookCount = guestBookRepository.countAllBySpot(spot).intValue(); + Integer likesCount = likesRepository.countBySpot(spot); + Boolean isFavorited = likesRepository.existsByMemberAndSpot(member, spot); - Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + GetSpotDetailRes getSpotDetailRes = GetSpotDetailRes.builder() + .spotId(spotId) + .memberId(spot.getMember().getId()) + .name(spot.getName()) + .info(spot.getInfo()) + .dongAreaId(spot.getDongArea()) + .detailAddress(spot.getDetailAddress()) + .latitude(spot.getLatitude()) + .longitude(spot.getLongitude()) + .image(getImageString(imageRepository.findBySpotId(spot.getId()))) + .stars(spot.getStars()) + .guestbookCount(guestbookCount) + .likesCount(likesCount) + .isFavorited(isFavorited) + .build(); - return getResponseEntity(spot); + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(getSpotDetailRes) + .build(); + + return ResponseEntity.ok(apiResponse); } @Transactional @@ -181,6 +216,7 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd return getResponseEntity(spot); } + //Spot 삭제 Method @Transactional public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index 3b0fa1aa..eb178317 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -37,11 +37,11 @@ public class Spot extends BaseEntity { @Schema(description = "위도", example = "36.5642886") @Column(name = "latitude", nullable = false) - private Float latitude; + private Double latitude; @Schema(description = "경도", example = "126.9275718") @Column(name = "longitude", nullable = false) - private Float longitude; + private Double longitude; @Schema(description = "별점 평균", example = "3.4") @Column(name = "stars") @@ -60,7 +60,7 @@ public class Spot extends BaseEntity { @Column(name = "detail_address", nullable = false) private String detailAddress; - public Spot(Long id, String name, String info, Float latitude, Float longitude, Float stars, Member member, String dongArea, String detailAddress) { + public Spot(Long id, String name, String info, Double latitude, Double longitude, Float stars, Member member, String dongArea, String detailAddress) { this.id = id; this.name = name; this.info = info; @@ -72,7 +72,7 @@ public Spot(Long id, String name, String info, Float latitude, Float longitude, this.detailAddress = detailAddress; } - public void updateSpot(String name, String info, Float latitude, Float longitude, String dongArea, String detailAddress) { + public void updateSpot(String name, String info, Double latitude, Double longitude, String dongArea, String detailAddress) { this.name = name; this.info = info; this.latitude = latitude; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 148fcea5..e8ada49c 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -26,10 +26,10 @@ public class CreateSpotRequestDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java index 0ffac459..f7751985 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/UpdateSpotRequestDto.java @@ -25,10 +25,10 @@ public class UpdateSpotRequestDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java b/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java new file mode 100644 index 00000000..3ab61c14 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java @@ -0,0 +1,71 @@ +package com.ttubeog.domain.spot.dto.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ttubeog.domain.benefit.domain.BenefitType; +import com.ttubeog.domain.store.domain.StoreType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GetSpotDetailRes { + + @Schema(description = "산책 스팟 ID") + private Long spotId; + + @Schema(description = "등록 유저 ID") + private Long memberId; + + @Schema(description = "매장 이름") + private String name; + + @Schema(description = "매장 정보") + private String info; + + @Schema(description = "지역(동) ID") + private String dongAreaId; + + @Schema(description = "상세 주소") + private String detailAddress; + + @Schema(description = "위도") + private Double latitude; + + @Schema(description = "경도") + private Double longitude; + + @Schema(description = "이미지 리스트") + private List image; + + @Schema(description = "별점") + private Float stars; + + @Schema(description = "방명록 수") + private Integer guestbookCount; + + @Schema(description = "좋아요 수") + private Integer likesCount; + + @Schema(description = "현재 유저의 좋아요 여부") + private Boolean isFavorited; + + @Builder + public GetSpotDetailRes(Long spotId, Long memberId, String name, String info, String dongAreaId, String detailAddress, Double latitude, Double longitude, List image, Float stars, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { + this.spotId = spotId; + this.memberId = memberId; + this.name = name; + this.info = info; + this.dongAreaId = dongAreaId; + this.detailAddress = detailAddress; + this.latitude = latitude; + this.longitude = longitude; + this.image = image; + this.stars = stars; + this.guestbookCount = guestbookCount; + this.likesCount = likesCount; + this.isFavorited = isFavorited; + } +} diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 64ae4c4c..086a8030 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -33,10 +33,10 @@ public class SpotResponseDto { private String info; @Schema(description = "위도", defaultValue = "36.5642886") - private Float latitude; + private Double latitude; @Schema(description = "경도", defaultValue = "126.9275718") - private Float longitude; + private Double longitude; @Schema(description = "이미지 리스트") private List image; From c1c4952dd60a86111ef98413de6f120b7776643c Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 18:49:43 +0900 Subject: [PATCH 311/356] =?UTF-8?q?[Chore]=20=EC=82=B0=EC=B1=85=EC=8A=A4?= =?UTF-8?q?=ED=8C=9F=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=88=84=EB=A5=B4?= =?UTF-8?q?=EB=8A=94=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/spot/application/SpotService.java | 10 ---------- .../domain/spot/presentation/SpotController.java | 6 ++++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 02a6c338..acf4086d 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,8 +1,6 @@ package com.ttubeog.domain.spot.application; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.benefit.domain.Benefit; -import com.ttubeog.domain.benefit.domain.BenefitType; import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; @@ -25,8 +23,6 @@ import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; -import com.ttubeog.domain.store.domain.Store; -import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.global.payload.ApiResponse; import com.ttubeog.global.payload.Message; @@ -38,7 +34,6 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.stream.Collectors; import static com.ttubeog.domain.image.application.ImageService.getImageString; @@ -246,9 +241,4 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { return ResponseEntity.ok(apiResponse); } - - @Transactional - public ResponseEntity likeSpot(HttpServletRequest request, Integer spotId) { - return null; - } } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 9f95a2e0..c616c5b9 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.guestbook.application.GuestBookService; +import com.ttubeog.domain.likes.application.LikesService; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.application.SpotService; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; @@ -30,6 +31,7 @@ public class SpotController { private final SpotService spotService; + private final LikesService likesService; /** @@ -383,8 +385,8 @@ public ResponseEntity deleteSpot( @PatchMapping("/{spotId}/likes") public ResponseEntity likeSpot( @CurrentUser HttpServletRequest request, - @RequestParam(name = "spotId") Integer spotId + @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return spotService.likeSpot(request, spotId); + return likesService.likesSpot(request, spotId); } } From c02f23f76814c298f8d88a8dc95a79666eea62ea Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 19:16:12 +0900 Subject: [PATCH 312/356] =?UTF-8?q?[Chore]=20swagger=20yml=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/swagger/application-springdoc.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/resources/swagger/application-springdoc.yml diff --git a/src/main/resources/swagger/application-springdoc.yml b/src/main/resources/swagger/application-springdoc.yml new file mode 100644 index 00000000..59bfb544 --- /dev/null +++ b/src/main/resources/swagger/application-springdoc.yml @@ -0,0 +1,14 @@ +springdoc: + default-consumes-media-type: application/json;charset=UTF-8 + default-produces-media-type: application/json;charset=UTF-8 + swagger-ui: + path: swagger + disable-swagger-default-url: true + display-request-duration: true + operations-sorter: method + doc-expansion: none + + # enabled: false + # query-config-enabled: false + # api-docs: + # enabled: false \ No newline at end of file From 9db9ce1910aceaabf21a5ee891e2b9670c17db79 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sun, 18 Feb 2024 19:25:46 +0900 Subject: [PATCH 313/356] =?UTF-8?q?[Feat]=20Image=20domain=20s3=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../domain/UuidImage/domain/UuidImage.java | 40 ++ .../repository/UuidImageRepository.java | 7 + .../domain/aws/s3/AmazonS3Manager.java | 48 +++ .../ttubeog/domain/aws/s3/S3PhotoService.java | 26 ++ .../application/GuestBookService.java | 69 +--- .../request/CreateGuestBookRequestDto.java | 5 +- .../presentation/GuestBookController.java | 3 +- .../image/application/ImageService.java | 349 ++++++++++++------ .../ttubeog/domain/image/domain/Image.java | 12 +- .../domain/image/domain/ImageType.java | 2 +- .../domain/repository/ImageRepository.java | 10 + .../dto/request/CreateImageRequestDto.java | 2 +- .../dto/request/UpdateImageRequestDto.java | 2 +- .../image/dto/response/ImageResponseDto.java | 4 +- .../exception/InvalidImageException.java | 2 +- .../exception/InvalidImageTypeException.java | 2 +- .../image/presentation/ImageController.java | 105 ++++++ .../store/application/StoreService.java | 4 +- .../ttubeog/global/config/AmazonConfig.java | 62 ++++ 20 files changed, 577 insertions(+), 179 deletions(-) create mode 100644 src/main/java/com/ttubeog/domain/UuidImage/domain/UuidImage.java create mode 100644 src/main/java/com/ttubeog/domain/UuidImage/domain/repository/UuidImageRepository.java create mode 100644 src/main/java/com/ttubeog/domain/aws/s3/AmazonS3Manager.java create mode 100644 src/main/java/com/ttubeog/domain/aws/s3/S3PhotoService.java create mode 100644 src/main/java/com/ttubeog/domain/image/presentation/ImageController.java create mode 100644 src/main/java/com/ttubeog/global/config/AmazonConfig.java diff --git a/build.gradle b/build.gradle index 4b00d61a..2708da94 100644 --- a/build.gradle +++ b/build.gradle @@ -62,6 +62,8 @@ dependencies { runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.1.94.Final:osx-aarch_64") } + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + } diff --git a/src/main/java/com/ttubeog/domain/UuidImage/domain/UuidImage.java b/src/main/java/com/ttubeog/domain/UuidImage/domain/UuidImage.java new file mode 100644 index 00000000..3cd52649 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/UuidImage/domain/UuidImage.java @@ -0,0 +1,40 @@ +package com.ttubeog.domain.UuidImage.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Getter +@Builder +@Table(name = "uuid_image") +public class UuidImage { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(unique = true) + private String uuid; + + @Column(name = "image_url") + private String imageUrl; + + public UuidImage(Long id, String uuid, String imageUrl) { + this.id = id; + this.uuid = uuid; + this.imageUrl = imageUrl; + } + + public void updateImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } +} diff --git a/src/main/java/com/ttubeog/domain/UuidImage/domain/repository/UuidImageRepository.java b/src/main/java/com/ttubeog/domain/UuidImage/domain/repository/UuidImageRepository.java new file mode 100644 index 00000000..3a7cab75 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/UuidImage/domain/repository/UuidImageRepository.java @@ -0,0 +1,7 @@ +package com.ttubeog.domain.UuidImage.domain.repository; + +import com.ttubeog.domain.UuidImage.domain.UuidImage; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UuidImageRepository extends JpaRepository { +} diff --git a/src/main/java/com/ttubeog/domain/aws/s3/AmazonS3Manager.java b/src/main/java/com/ttubeog/domain/aws/s3/AmazonS3Manager.java new file mode 100644 index 00000000..b16d4cf4 --- /dev/null +++ b/src/main/java/com/ttubeog/domain/aws/s3/AmazonS3Manager.java @@ -0,0 +1,48 @@ +package com.ttubeog.domain.aws.s3; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.ttubeog.domain.UuidImage.domain.UuidImage; +import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.global.config.AmazonConfig; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class AmazonS3Manager { + + private final AmazonS3 amazonS3; + + private final AmazonConfig amazonConfig; + + public String uploadFile(String keyName, MultipartFile file) { + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(file.getSize()); + try { + amazonS3.putObject(new PutObjectRequest(amazonConfig.getBucket(), keyName, file.getInputStream(), metadata)); + }catch (IOException e) { + log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); + } + + return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); + } + + public String generateSpotKeyName(Image image) { + return amazonConfig.getSpotPath() + '/' + image.getUuid(); + } + + public String generateStoreKeyName(Image image) { + return amazonConfig.getStorePath() + '/' + image.getUuid(); + } + + public String generateGuestBookKeyName(Image image) { + return amazonConfig.getGuestBookPath() + '/' + image.getUuid(); + } +} diff --git a/src/main/java/com/ttubeog/domain/aws/s3/S3PhotoService.java b/src/main/java/com/ttubeog/domain/aws/s3/S3PhotoService.java new file mode 100644 index 00000000..2ecd93db --- /dev/null +++ b/src/main/java/com/ttubeog/domain/aws/s3/S3PhotoService.java @@ -0,0 +1,26 @@ +package com.ttubeog.domain.aws.s3; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.S3ObjectResource; +import com.amazonaws.services.s3.model.S3Object; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +@Service +public class S3PhotoService { + + private final AmazonS3 amazonS3; + + public S3PhotoService(AmazonS3 amazonS3) { + this.amazonS3 = amazonS3; + } + + public InputStream downloadPhotoFromS3(String bucketName, String key) throws IOException { + S3Object object = amazonS3.getObject(bucketName, key); + + return new ByteArrayInputStream(object.getObjectContent().readAllBytes()); + } +} diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 5f485e4c..f5fed815 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,20 +1,17 @@ package com.ttubeog.domain.guestbook.application; +import com.ttubeog.domain.UuidImage.domain.UuidImage; +import com.ttubeog.domain.UuidImage.domain.repository.UuidImageRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.aws.s3.AmazonS3Manager; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.GuestBookType; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.guestbook.dto.request.CreateGuestBookRequestDto; -import com.ttubeog.domain.guestbook.dto.request.UpdateGuestBookRequestDto; import com.ttubeog.domain.guestbook.dto.response.GuestBookResponseDto; import com.ttubeog.domain.guestbook.exception.InvalidGuestBookException; import com.ttubeog.domain.guestbook.exception.InvalidGuestBookIdException; -import com.ttubeog.domain.image.application.ImageService; -import com.ttubeog.domain.image.domain.Image; -import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; -import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; @@ -36,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.UUID; @RequiredArgsConstructor @Service @@ -47,8 +45,11 @@ public class GuestBookService { private final SpotRepository spotRepository; private final StoreRepository storeRepository; private final ImageRepository imageRepository; + private final UuidImageRepository uuidImageRepository; - private final ImageService imageService; + //private final ImageService imageService; + + private final AmazonS3Manager amazonS3Manager; private final JwtTokenProvider jwtTokenProvider; @@ -130,14 +131,6 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest guestBookRepository.save(guestBook); - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(createGuestBookRequestDto.getImage()) - .imageType(ImageType.GUESTBOOK) - .placeId(guestBook.getId()) - .build(); - imageService.createImage(createImageRequestDto); - - if (createGuestBookRequestDto.getGuestBookType().equals(GuestBookType.SPOT)) { spot = spotRepository.findById(createGuestBookRequestDto.getSpotId()).orElseThrow(InvalidSpotIdException::new); @@ -173,25 +166,13 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest return getResponseEntity(guestBook); } - - // GuestBook 을 Id(PK) 값으로 찾는 Method 입니다. 현재 사용하지 않습니다. - public ResponseEntity findByGuestBookId(HttpServletRequest request, Long guestBookId) { - Long memberId = jwtTokenProvider.getMemberId(request); - - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - - GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); - - return getResponseEntity(guestBook); - } - // Spot ID 로 GuestBook 을 조회하는 Method 입니다. public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidStoreIdException::new); Page guestBookPage = guestBookRepository.findAllBySpot(spot, PageRequest.of(pageNum, 10)); @@ -217,6 +198,7 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long return ResponseEntity.ok(apiResponse); } + // Store ID 로 GuestBook 을 조회하는 Method 입니다. public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -250,35 +232,6 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long } - // GuestBook 을 Update 하는 Method 입니다. 현재 따로 사용하지 않습니다. - @Transactional - public ResponseEntity updateGuestBook(HttpServletRequest request, Long guestBookId, UpdateGuestBookRequestDto updateGuestBookRequestDto) { - - Long memberId = jwtTokenProvider.getMemberId(request); - - memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - - GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidGuestBookIdException::new); - - Image image = imageRepository.findByGuestBookId(guestBook.getId()).orElseThrow(InvalidImageException::new); - - imageService.deleteImage(image.getId()); - - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(updateGuestBookRequestDto.getImage()) - .imageType(ImageType.GUESTBOOK) - .placeId(guestBookId) - .build(); - - Image newImage = imageRepository.findById(imageService.createImage(createImageRequestDto).getId()).orElseThrow(InvalidImageException::new); - - guestBook.updateGuestBook(updateGuestBookRequestDto.getContent(), updateGuestBookRequestDto.getStar(), newImage); - - guestBookRepository.save(guestBook); - - return getResponseEntity(guestBook); - } - // GuestBook 을 하나 Delete 하는 Method 입니다. @Transactional public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestBookId) { @@ -294,7 +247,7 @@ public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestB guestBookRepository.delete(guestBook); - imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); + //imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); ApiResponse apiResponse = ApiResponse.builder() .check(true) diff --git a/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java index 46e24e81..5bdf4738 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java +++ b/src/main/java/com/ttubeog/domain/guestbook/dto/request/CreateGuestBookRequestDto.java @@ -1,8 +1,11 @@ package com.ttubeog.domain.guestbook.dto.request; import com.ttubeog.domain.guestbook.domain.GuestBookType; +import lombok.Data; import lombok.Getter; +import org.springframework.web.multipart.MultipartFile; +@Data @Getter public class CreateGuestBookRequestDto { @@ -16,6 +19,4 @@ public class CreateGuestBookRequestDto { private Float star; - private String image; - } diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 85c588fb..5a77c044 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -17,6 +17,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; @Tag(name = "GuestBook", description = "GuestBook API(방명록 API)") @RequiredArgsConstructor @@ -61,7 +62,7 @@ public class GuestBookController { @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createGuestBook( @CurrentUser HttpServletRequest request, - @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto + @RequestPart CreateGuestBookRequestDto createGuestBookRequestDto ) throws JsonProcessingException { return guestBookService.createGuestBook(request, createGuestBookRequestDto); } diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index 5ff0d528..d2704508 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -1,5 +1,8 @@ package com.ttubeog.domain.image.application; +import com.ttubeog.domain.auth.security.JwtTokenProvider; +import com.ttubeog.domain.aws.s3.AmazonS3Manager; +import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.guestbook.exception.InvalidGuestBookIdException; import com.ttubeog.domain.image.domain.Image; @@ -10,16 +13,26 @@ import com.ttubeog.domain.image.dto.response.ImageResponseDto; import com.ttubeog.domain.image.exception.InvalidImageException; import com.ttubeog.domain.image.exception.InvalidImageTypeException; +import com.ttubeog.domain.member.domain.repository.MemberRepository; +import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.spot.domain.Spot; import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; +import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; +import com.ttubeog.global.payload.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; @RequiredArgsConstructor @Service @@ -30,149 +43,269 @@ public class ImageService { private final SpotRepository spotRepository; private final StoreRepository storeRepository; private final GuestBookRepository guestBookRepository; + private final MemberRepository memberRepository; - public static List getImageString(List imageList) { - List imageString = new ArrayList<>(); + private final JwtTokenProvider jwtTokenProvider; - for (Image image : imageList) { - imageString.add(imageString.size(), image.getImage()); - } + private final AmazonS3Manager amazonS3Manager; - return imageString; - } - public ImageResponseDto findById(Long imageId) { - Image image = imageRepository.findById(imageId).orElseThrow(InvalidImageException::new); - ImageResponseDto imageResponseDto = new ImageResponseDto(); - if (image.getImageType().equals(ImageType.SPOT)) { - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .image(image.getImage()) - .imageType(image.getImageType()) - .placeId(image.getSpot().getId()) - .build(); - } else if (image.getImageType().equals(ImageType.STORE)) { - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .image(image.getImage()) - .imageType(image.getImageType()) - .placeId(image.getStore().getId()) + @Transactional + public ResponseEntity createSpotImage(HttpServletRequest request, Long spotId, List fileList) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + List imageResponseDtoList = fileList.stream().map(multipartFile -> { + String uuid = UUID.randomUUID().toString(); + + Image image = Image.builder() + .uuid(uuid) + .imageType(ImageType.SPOT) + .spot(spot) .build(); - } else if (image.getImageType().equals(ImageType.GUESTBOOK)) { - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .image(image.getImage()) - .imageType(image.getImageType()) - .placeId(image.getGuestBook().getId()) + + String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateStoreKeyName(image), multipartFile); + image.updateImageUrl(imageUrl); + Image savedImage = imageRepository.save(image); + + return ImageResponseDto.builder() + .id(savedImage.getId()) + .uuid(savedImage.getUuid()) + .image(savedImage.getImage()) + .imageType(ImageType.SPOT) + .placeId(savedImage.getSpot().getId()) .build(); - } else { - throw new InvalidImageTypeException(); - } + }).collect(Collectors.toList()); - return imageResponseDto; + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); } + @Transactional - public ImageResponseDto createImage(CreateImageRequestDto createImageRequestDto) { - - Image image; - ImageResponseDto imageResponseDto; - if (createImageRequestDto.getImageType().equals(ImageType.SPOT)) { - image = Image.builder() - .image(createImageRequestDto.getImage()) - .imageType(createImageRequestDto.getImageType()) - .spot(spotRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)) - .build(); + public ResponseEntity createStoreImage(HttpServletRequest request, Long storeId, List fileList) { - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getSpot().getId()) - .build(); - } else if (createImageRequestDto.getImageType().equals(ImageType.STORE)){ - image = Image.builder() - .image(createImageRequestDto.getImage()) - .imageType(createImageRequestDto.getImageType()) - .store(storeRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidStoreIdException::new)) - .build(); + Long memberId = jwtTokenProvider.getMemberId(request); - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getStore().getId()) - .build(); - } else if (createImageRequestDto.getImageType().equals(ImageType.GUESTBOOK)) { - image = Image.builder() - .image(createImageRequestDto.getImage()) - .imageType(createImageRequestDto.getImageType()) - .guestBook(guestBookRepository.findById(createImageRequestDto.getPlaceId()).orElseThrow(InvalidGuestBookIdException::new)) + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); + + List imageResponseDtoList = fileList.stream().map(multipartFile -> { + String uuid = UUID.randomUUID().toString(); + + Image image = Image.builder() + .uuid(uuid) + .imageType(ImageType.STORE) + .store(store) .build(); - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getGuestBook().getId()) + String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateStoreKeyName(image), multipartFile); + image.updateImageUrl(imageUrl); + Image savedImage = imageRepository.save(image); + + return ImageResponseDto.builder() + .id(savedImage.getId()) + .uuid(savedImage.getUuid()) + .image(savedImage.getImage()) + .imageType(ImageType.STORE) + .placeId(savedImage.getStore().getId()) .build(); - } else { - throw new InvalidImageTypeException(); - } + }).collect(Collectors.toList()); - imageRepository.save(image); + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); - return imageResponseDto; + return ResponseEntity.ok(apiResponse); } + @Transactional - public ImageResponseDto updateImage(UpdateImageRequestDto updateImageRequestDto) { + public ResponseEntity createGuestBookImage(HttpServletRequest request, Long guestBookId, List fileList) { - Image image = imageRepository.findById(updateImageRequestDto.getId()).orElseThrow(InvalidImageException::new); + Long memberId = jwtTokenProvider.getMemberId(request); - if (!image.getImageType().equals(updateImageRequestDto.getImageType())) { - throw new InvalidImageTypeException(); - } + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); - ImageResponseDto imageResponseDto; + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidStoreIdException::new); + List imageResponseDtoList = fileList.stream().map(multipartFile -> { + String uuid = UUID.randomUUID().toString(); + Image image = Image.builder() + .uuid(uuid) + .imageType(ImageType.GUESTBOOK) + .guestBook(guestBook) + .build(); - if (updateImageRequestDto.getImageType().equals(ImageType.SPOT)) { - image.updateImage(updateImageRequestDto.getImage(), spotRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidSpotIdException::new)); + String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateStoreKeyName(image), multipartFile); + image.updateImageUrl(imageUrl); + Image savedImage = imageRepository.save(image); - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getSpot().getId()) + return ImageResponseDto.builder() + .id(savedImage.getId()) + .uuid(savedImage.getUuid()) + .image(savedImage.getImage()) + .imageType(ImageType.GUESTBOOK) + .placeId(savedImage.getGuestBook().getId()) .build(); - } else if (updateImageRequestDto.getImageType().equals(ImageType.STORE)){ - image.updateImage(updateImageRequestDto.getImage(), storeRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidStoreIdException::new)); + }).collect(Collectors.toList()); - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getStore().getId()) - .build(); - } else if (updateImageRequestDto.getImageType().equals(ImageType.GUESTBOOK)) { - image.updateImage(updateImageRequestDto.getImage(), guestBookRepository.findById(updateImageRequestDto.getPlaceId()).orElseThrow(InvalidGuestBookIdException::new)); + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); - imageResponseDto = ImageResponseDto.builder() - .id(image.getId()) - .imageType(image.getImageType()) - .placeId(image.getGuestBook().getId()) - .build(); - } else { - throw new InvalidImageTypeException(); - } + return ResponseEntity.ok(apiResponse); + } + + + public ResponseEntity findImageBySpotId(HttpServletRequest request, Long spotId) { - imageRepository.save(image); + Long memberId = jwtTokenProvider.getMemberId(request); - return imageResponseDto; + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + List imageList = imageRepository.findAllBySpot(spot); + + List imageResponseDtoList = imageList.stream().map( + image -> ImageResponseDto.builder() + .id(image.getId()) + .uuid(image.getUuid()) + .image(image.getImage()) + .imageType(ImageType.SPOT) + .placeId(image.getSpot().getId()) + .build() + ).toList(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); } + + public ResponseEntity findImageByStoreId(HttpServletRequest request, Long storeId) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + Store store = storeRepository.findById(storeId).orElseThrow(InvalidSpotIdException::new); + + List imageList = imageRepository.findAllByStore(store); + + List imageResponseDtoList = imageList.stream().map( + image -> ImageResponseDto.builder() + .id(image.getId()) + .uuid(image.getUuid()) + .image(image.getImage()) + .imageType(ImageType.STORE) + .placeId(image.getStore().getId()) + .build() + ).toList(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + + public ResponseEntity findImageByGuestBookId(HttpServletRequest request, Long guestBookId) { + + Long memberId = jwtTokenProvider.getMemberId(request); + + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidSpotIdException::new); + + List imageList = imageRepository.findAllByGuestBook(guestBook); + + List imageResponseDtoList = imageList.stream().map( + image -> ImageResponseDto.builder() + .id(image.getId()) + .uuid(image.getUuid()) + .image(image.getImage()) + .imageType(ImageType.GUESTBOOK) + .placeId(image.getGuestBook().getId()) + .build() + ).toList(); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(imageResponseDtoList) + .build(); + + return ResponseEntity.ok(apiResponse); + } + + + @Transactional + public ResponseEntity deleteImageBySpotId(Long spotId) { + + Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); + + List imageList = imageRepository.findAllBySpot(spot); + imageRepository.deleteAll(imageList); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information("정상적으로 삭제되었습니다.") + .build(); + + return ResponseEntity.ok(apiResponse); + } + + + @Transactional + public ResponseEntity deleteImageByStoreId(Long storeId) { + + Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); + + List imageList = imageRepository.findAllByStore(store); + imageRepository.deleteAll(imageList); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information("정상적으로 삭제되었습니다.") + .build(); + + return ResponseEntity.ok(apiResponse); + } + + @Transactional - public void deleteImage(Long imageId) { + public ResponseEntity deleteImageByGuestBookId(Long guestBookId) { + + GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidSpotIdException::new); - Image image = imageRepository.findById(imageId).orElseThrow(InvalidImageException::new); - imageRepository.delete(image); + List imageList = imageRepository.findAllByGuestBook(guestBook); + imageRepository.deleteAll(imageList); + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information("정상적으로 삭제되었습니다.") + .build(); + + return ResponseEntity.ok(apiResponse); } -} + +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/domain/Image.java b/src/main/java/com/ttubeog/domain/image/domain/Image.java index bcf46099..94cb5e86 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/Image.java +++ b/src/main/java/com/ttubeog/domain/image/domain/Image.java @@ -24,6 +24,9 @@ public class Image extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "uuid", unique = true) + private String uuid; + @Column(name = "image", nullable = false) private String image; @@ -42,8 +45,9 @@ public class Image extends BaseEntity { @JoinColumn(name = "guestbook_id") private GuestBook guestBook; - public Image(Long id, String image, ImageType imageType, Spot spot, Store store, GuestBook guestBook) { + public Image(Long id, String uuid, String image, ImageType imageType, Spot spot, Store store, GuestBook guestBook) { this.id = id; + this.uuid = uuid; this.image = image; this.imageType = imageType; this.spot = spot; @@ -65,4 +69,8 @@ public void updateImage(String image, GuestBook guestBook) { this.image = image; this.guestBook = guestBook; } -} + + public void updateImageUrl(String image) { + this.image = image; + } +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/domain/ImageType.java b/src/main/java/com/ttubeog/domain/image/domain/ImageType.java index b143f3b3..b041ab6a 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/ImageType.java +++ b/src/main/java/com/ttubeog/domain/image/domain/ImageType.java @@ -7,4 +7,4 @@ public enum ImageType { SPOT, STORE, GUESTBOOK; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java index 844643da..53d8da13 100644 --- a/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java +++ b/src/main/java/com/ttubeog/domain/image/domain/repository/ImageRepository.java @@ -1,6 +1,9 @@ package com.ttubeog.domain.image.domain.repository; +import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.image.domain.Image; +import com.ttubeog.domain.spot.domain.Spot; +import com.ttubeog.domain.store.domain.Store; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -18,4 +21,11 @@ public interface ImageRepository extends JpaRepository { List findByStoreId(Long id); Optional findByGuestBookId(Long id); + + List findAllBySpot(Spot spot); + + List findAllByStore(Store store); + + List findAllByGuestBook(GuestBook guestBook); + } diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java index 4ba09ee1..d255e82b 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/request/CreateImageRequestDto.java @@ -14,4 +14,4 @@ public class CreateImageRequestDto { public ImageType imageType; public Long placeId; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java index c42b4c2b..c5ced3bd 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/request/UpdateImageRequestDto.java @@ -15,4 +15,4 @@ public class UpdateImageRequestDto { public String image; public ImageType imageType; public Long placeId; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java index 88f61644..e7593f33 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; @Getter @Builder @@ -13,8 +14,9 @@ public class ImageResponseDto { public Long id; + public String uuid; public String image; public ImageType imageType; public Long placeId; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java index 4c50a271..1d55559b 100644 --- a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java +++ b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageException.java @@ -5,4 +5,4 @@ public class InvalidImageException extends RuntimeException { public InvalidImageException() { super("유효하지 않은 이미지입니다."); } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java index d339b73f..e7f9884b 100644 --- a/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java +++ b/src/main/java/com/ttubeog/domain/image/exception/InvalidImageTypeException.java @@ -5,4 +5,4 @@ public class InvalidImageTypeException extends RuntimeException { public InvalidImageTypeException() { super("올바르지 않은 이미지 타입입니다."); } -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java new file mode 100644 index 00000000..c02bda4e --- /dev/null +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -0,0 +1,105 @@ +package com.ttubeog.domain.image.presentation; + +import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.global.config.security.token.CurrentUser; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Tag(name = "Image", description = "Image API(이미지 API)") +@RequiredArgsConstructor +@RestController +@RequestMapping("api/v1/image") +public class ImageController { + + private final ImageService imageService; + + @PostMapping(value = "/spot", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createSpotImage( + @CurrentUser HttpServletRequest request, + @RequestParam Long spotId, + @RequestPart List fileList + ) { + return imageService.createSpotImage(request, spotId, fileList); + } + + @PostMapping(value = "/store", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createStoreImage( + @CurrentUser HttpServletRequest request, + @RequestParam Long storeId, + @RequestPart List fileList + ) { + return imageService.createStoreImage(request, storeId, fileList); + } + + @PostMapping(value = "/guestbook", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public ResponseEntity createGuestBookImage( + @CurrentUser HttpServletRequest request, + @RequestParam Long guestBookId, + @RequestPart List fileList + ) { + return imageService.createGuestBookImage(request, guestBookId, fileList); + } + + @GetMapping(value = "/{spotId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findImageBySpotId( + @CurrentUser HttpServletRequest request, + @RequestParam Long spotId + ) { + return imageService.findImageBySpotId(request, spotId); + } + + @GetMapping(value = "/{storeId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findImageByStoreId( + @CurrentUser HttpServletRequest request, + @RequestParam Long storeId + ) { + return imageService.findImageByStoreId(request, storeId); + } + + @GetMapping(value = "/{guestBookId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity findImageByGuestBookId( + @CurrentUser HttpServletRequest request, + @RequestParam Long guestBookId + ) { + return imageService.findImageByGuestBookId(request, guestBookId); + } + + + @DeleteMapping(value = "/{spotId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteImageBySpotId( + @RequestParam Long spotId + ) { + return imageService.deleteImageBySpotId(spotId); + } + + @DeleteMapping(value = "/{storeId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteImageByStoreId( + @RequestParam Long storeId + ) { + return imageService.deleteImageByStoreId(storeId); + } + + @DeleteMapping(value = "/{guestBookId}") + @ResponseStatus(value = HttpStatus.OK) + public ResponseEntity deleteImageByGuestBookId( + @RequestParam Long guestBookId + ) { + return imageService.deleteImageByGuestBookId(guestBookId); + } +} diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 57141ec8..f4ec75e0 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.store.application; -import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; @@ -27,7 +26,6 @@ import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; -import com.ttubeog.domain.store.exception.InvalidDongAreaException; import com.ttubeog.domain.store.exception.UnathorizedMemberException; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.domain.member.domain.Member; @@ -44,6 +42,8 @@ import static com.ttubeog.domain.image.application.ImageService.getImageString; +//import static com.ttubeog.domain.image.application.ImageService.getImageString; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) diff --git a/src/main/java/com/ttubeog/global/config/AmazonConfig.java b/src/main/java/com/ttubeog/global/config/AmazonConfig.java new file mode 100644 index 00000000..ab0b8cba --- /dev/null +++ b/src/main/java/com/ttubeog/global/config/AmazonConfig.java @@ -0,0 +1,62 @@ +package com.ttubeog.global.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import jakarta.annotation.PostConstruct; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Getter +public class AmazonConfig { + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("${cloud.aws.s3.path.spot}") + private String spotPath; + + @Value("${cloud.aws.s3.path.store}") + private String storePath; + + @Value("${cloud.aws.s3.path.guest_book}") + private String guestBookPath; + + + private AWSCredentials awsCredentials; + + @PostConstruct + public void init() { + this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + } + + @Bean + public AmazonS3 amazonS3() { + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } + + @Bean + public AWSCredentialsProvider awsCredentialsProvider() { + return new AWSStaticCredentialsProvider(awsCredentials); + } + +} From b8d8f289e11a9e7af559f50e91bed834337d3cc1 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sun, 18 Feb 2024 19:30:05 +0900 Subject: [PATCH 314/356] =?UTF-8?q?[refac]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/spot/application/SpotService.java | 30 --------------- .../spot/dto/response/SpotResponseDto.java | 3 -- .../store/application/StoreService.java | 38 ------------------- .../store/dto/response/GetStoreDetailRes.java | 6 +-- 4 files changed, 1 insertion(+), 76 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 012569ea..c70b3f6b 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -31,7 +31,6 @@ import java.util.List; -import static com.ttubeog.domain.image.application.ImageService.getImageString; @RequiredArgsConstructor @Service @@ -59,7 +58,6 @@ private ResponseEntity getResponseEntity(Spot spot) { .info(spot.getInfo()) .latitude(spot.getLatitude()) .longitude(spot.getLongitude()) - .image(getImageString(imageRepository.findBySpotId(spot.getId()))) .stars(spot.getStars()) .build(); @@ -103,17 +101,6 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques spotRepository.save(spot); - // 이미지 저장 - List imageList = createSpotRequestDto.getImage(); - for (String s : imageList) { - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(s) - .imageType(ImageType.SPOT) - .placeId(spot.getId()) - .build(); - imageService.createImage(createImageRequestDto); - } - return getResponseEntity(spot); } @@ -161,23 +148,6 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd spotRepository.save(spot); - List imageList = imageRepository.findBySpotId(spotId); - - for (Image image : imageList) { - imageService.deleteImage(image.getId()); - } - - List imageStringList = updateSpotRequestDto.getImage(); - - for (String s : imageStringList) { - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(s) - .imageType(ImageType.SPOT) - .placeId(spotId) - .build(); - imageService.createImage(createImageRequestDto); - } - return getResponseEntity(spot); } diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index 64ae4c4c..d4d270d8 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -38,9 +38,6 @@ public class SpotResponseDto { @Schema(description = "경도", defaultValue = "126.9275718") private Float longitude; - @Schema(description = "이미지 리스트") - private List image; - @Schema(description = "평균 별점", defaultValue = "4.5") private Float stars; diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index f4ec75e0..8c73d6a9 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.store.application; -import com.ttubeog.domain.area.domain.repository.DongAreaRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.benefit.domain.Benefit; import com.ttubeog.domain.benefit.domain.BenefitType; @@ -9,11 +8,8 @@ import com.ttubeog.domain.benefit.domain.repository.MemberBenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; -import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; -import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.likes.domain.Likes; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -40,9 +36,6 @@ import java.util.List; import java.util.stream.Collectors; -import static com.ttubeog.domain.image.application.ImageService.getImageString; - -//import static com.ttubeog.domain.image.application.ImageService.getImageString; @RequiredArgsConstructor @Service @@ -51,13 +44,11 @@ public class StoreService { private final StoreRepository storeRepository; private final MemberRepository memberRepository; - private final DongAreaRepository dongAreaRepository; private final ImageRepository imageRepository; private final BenefitRepository benefitRepository; private final MemberBenefitRepository memberBenefitRepository; private final GuestBookRepository guestBookRepository; private final LikesRepository likesRepository; - private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; // 매장 등록 @@ -86,16 +77,6 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore storeRepository.save(store); - // 이미지 저장 - List imageList = registerStoreReq.getImage(); - for (String s : imageList) { - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(s) - .imageType(ImageType.STORE) - .placeId(store.getId()) - .build(); - imageService.createImage(createImageRequestDto); - } RegisterStoreRes registerStoreRes = RegisterStoreRes.builder() .storeId(store.getId()) @@ -106,7 +87,6 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) .build(); @@ -146,22 +126,6 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq storeRepository.save(store); - List imageList = imageRepository.findByStoreId(store.getId()); - - for (Image image : imageList) { - imageService.deleteImage(image.getId()); - } - - List imageStringList = updateStoreReq.getImage(); - - for (String s : imageStringList) { - CreateImageRequestDto createImageRequestDto = CreateImageRequestDto.builder() - .image(s) - .imageType(ImageType.STORE) - .placeId(store.getId()) - .build(); - imageService.createImage(createImageRequestDto); - } UpdateStoreRes updateStoreRes = UpdateStoreRes.builder() .storeId(store.getId()) @@ -170,7 +134,6 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) .build(); @@ -258,7 +221,6 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .detailAddress(store.getDetailAddress()) .latitude(store.getLatitude()) .longitude(store.getLongitude()) - .image(getImageString(imageRepository.findByStoreId(store.getId()))) .stars(store.getStars()) .type(store.getType()) .storeBenefits(storeBenefits) diff --git a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java index 71eec7dd..0b82fe43 100644 --- a/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java +++ b/src/main/java/com/ttubeog/domain/store/dto/response/GetStoreDetailRes.java @@ -37,9 +37,6 @@ public class GetStoreDetailRes { @Schema(description = "경도") private Double longitude; - @Schema(description = "이미지 리스트") - private List image; - @Schema(description = "별점") private Float stars; @@ -60,7 +57,7 @@ public class GetStoreDetailRes { @Builder public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, String dongAreaId, - String detailAddress, Double latitude, Double longitude, List image, Float stars, + String detailAddress, Double latitude, Double longitude, Float stars, StoreType type, List storeBenefits, Integer guestbookCount, Integer likesCount, Boolean isFavorited) { this.storeId = storeId; this.memberId = memberId; @@ -70,7 +67,6 @@ public GetStoreDetailRes(Long storeId, Long memberId, String name, String info, this.detailAddress = detailAddress; this.latitude = latitude; this.longitude = longitude; - this.image = image; this.stars = stars; this.type = type; this.storeBenefits = storeBenefits; From 6940213fffdf7307001b678a93aa04882ce3e70a Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 19:30:07 +0900 Subject: [PATCH 315/356] =?UTF-8?q?[Chore]=20=EC=9C=84=EB=8F=84=EA=B2=BD?= =?UTF-8?q?=EB=8F=84=20=EC=9E=90=EB=A3=8C=ED=98=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Float -> Double --- .../domain/comment/application/CommentService.java | 10 +++++----- .../com/ttubeog/domain/comment/domain/Comment.java | 4 ++-- .../domain/comment/dto/request/GetCommentReq.java | 4 ++-- .../domain/comment/dto/request/WriteCommentReq.java | 4 ++-- .../domain/comment/dto/response/WriteCommentRes.java | 6 +++--- .../ttubeog/domain/place/application/PlaceService.java | 5 ++--- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index 276b17d4..d24168ca 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -118,8 +118,8 @@ public List getAllComments() { // AR뷰를 위한 댓글 조회 public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { - Float userLatitude = getCommentReq.getLatitude(); - Float userLongitude = getCommentReq.getLongitude(); + Double userLatitude = getCommentReq.getLatitude(); + Double userLongitude = getCommentReq.getLongitude(); List allComments = getAllComments(); Double radius = 20.0; // 반경값 확인 필요 @@ -127,8 +127,8 @@ public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { for (Comment comment : allComments) { - Float commentLatitude = comment.getLatitude(); - Float commentLongitude = comment.getLongitude(); + Double commentLatitude = comment.getLatitude(); + Double commentLongitude = comment.getLongitude(); double distance = calculateDistance(userLatitude, userLongitude, commentLatitude, commentLongitude); @@ -153,7 +153,7 @@ public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { } // 거리 계산 - private double calculateDistance(Float lat1, Float lon1, Float lat2, Float lon2) { + private double calculateDistance(Double lat1, Double lon1, Double lat2, Double lon2) { double R = 6371; // 지구 반지름 double dLat = Math.toRadians(lat2 - lat1); diff --git a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java index 6d4f8c01..2360d223 100644 --- a/src/main/java/com/ttubeog/domain/comment/domain/Comment.java +++ b/src/main/java/com/ttubeog/domain/comment/domain/Comment.java @@ -21,10 +21,10 @@ public class Comment extends BaseEntity { private String content; @Column(name = "latitude") - private Float latitude; + private Double latitude; @Column(name = "longitude") - private Float longitude; + private Double longitude; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java index 5c16e981..41f41b64 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/GetCommentReq.java @@ -7,9 +7,9 @@ public class GetCommentReq { @Schema(description = "사용자 위치 위도값") - private Float latitude; + private Double latitude; @Schema(description = "사용자 위치 경도값") - private Float longitude; + private Double longitude; } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java index d0541d7f..9eae0f16 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/request/WriteCommentReq.java @@ -10,7 +10,7 @@ public class WriteCommentReq { @Schema(description = "댓글 내용") private String content; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; } diff --git a/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java index a3b78a19..546aaa7e 100644 --- a/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java +++ b/src/main/java/com/ttubeog/domain/comment/dto/response/WriteCommentRes.java @@ -17,13 +17,13 @@ public class WriteCommentRes { private String content; @Schema(description = "위도") - private Float latitude; + private Double latitude; @Schema(description = "경도") - private Float longitude; + private Double longitude; @Builder - public WriteCommentRes(Long commentId, Long memberId, String content, Float latitude, Float longitude) { + public WriteCommentRes(Long commentId, Long memberId, String content, Double latitude, Double longitude) { this.commentId = commentId; this.memberId = memberId; this.content = content; diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index c848c739..89f712b4 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -151,9 +151,8 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { .memberId(spot.getMember().getId()) .name(spot.getName()) .info(spot.getInfo()) - // 위도, 경도 double로 변경 필요 - //.latitude(spot.getLatitude()) - //.longitude(spot.getLongitude()) + .latitude(spot.getLatitude()) + .longitude(spot.getLongitude()) .image(representativeImageUrl) .stars(spot.getStars()) .guestbookCount(intValue(guestBookRepository.countAllBySpot(spot))) From d654ed64b6f14a67ed864f6e3af8a803f6f597c4 Mon Sep 17 00:00:00 2001 From: Dustbox Date: Sun, 18 Feb 2024 19:47:07 +0900 Subject: [PATCH 316/356] =?UTF-8?q?[Chore]=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 5c66865b..3e6d3565 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -131,7 +131,6 @@ public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { .detailAddress(spot.getDetailAddress()) .latitude(spot.getLatitude()) .longitude(spot.getLongitude()) - .image(getImageString(imageRepository.findBySpotId(spot.getId()))) .stars(spot.getStars()) .guestbookCount(guestbookCount) .likesCount(likesCount) From bfe6d2e4ed26b7ec5034f738c4dea43f20f5154d Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Sun, 18 Feb 2024 19:54:46 +0900 Subject: [PATCH 317/356] =?UTF-8?q?[Fix]=20dong=5Farea=20=ED=98=95?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/store/domain/Store.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index 32d6061a..a72a1a7f 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -45,7 +45,7 @@ public class Store extends BaseEntity { @Enumerated(EnumType.STRING) private StoreType type; - @Column(name = "dong_area_id") + @Column(name = "dong_area") private String dongArea; @ManyToOne(fetch = FetchType.LAZY) From 18b16f73a13fe95452b51fb02c9a05a668dc39a2 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 20:51:05 +0900 Subject: [PATCH 318/356] =?UTF-8?q?[Chore]=20spot=20=EC=A1=B0=ED=9A=8C=20r?= =?UTF-8?q?esponse=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/presentation/SpotController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index c616c5b9..8672a57f 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.spot.application.SpotService; import com.ttubeog.domain.spot.dto.request.CreateSpotRequestDto; import com.ttubeog.domain.spot.dto.request.UpdateSpotRequestDto; +import com.ttubeog.domain.spot.dto.response.GetSpotDetailRes; import com.ttubeog.domain.spot.dto.response.SpotResponseDto; import com.ttubeog.domain.spot.exception.AlreadyExistsSpotException; import com.ttubeog.domain.spot.exception.InvalidDongAreaException; @@ -121,7 +122,7 @@ public ResponseEntity createSpot( content = { @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = SpotResponseDto.class)) + array = @ArraySchema(schema = @Schema(implementation = GetSpotDetailRes.class)) ) } ), From a98d231a2aa25e340e8f2e8b5e4d8a58a9de946b Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 20:58:32 +0900 Subject: [PATCH 319/356] =?UTF-8?q?[Chore]=20Road=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EC=84=A4=EB=AA=85=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/road/application/RoadService.java | 6 ++++- .../dto/request/CreateRoadRequestDto.java | 16 +++++++++++- .../road/dto/response/RoadResponseDto.java | 25 +++++++++++++++---- .../road/presentation/RoadController.java | 4 +-- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 49a5ea05..0de83330 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -126,6 +126,7 @@ public ResponseEntity createRoad(HttpServletRequest request, CreateRoadReques .roadType(RoadType.SPOT) .spotId(road.getSpot().getId()) .memberId(road.getMember().getId()) + .memberName(road.getMember().getNickname()) .name(road.getName()) .roadCoordinateDoubleList(roadCoordinateDoubleListResponse) .build(); @@ -135,6 +136,7 @@ public ResponseEntity createRoad(HttpServletRequest request, CreateRoadReques .roadType(RoadType.STORE) .storeId(road.getStore().getId()) .memberId(road.getMember().getId()) + .memberName(road.getMember().getNickname()) .name(road.getName()) .roadCoordinateDoubleList(roadCoordinateDoubleListResponse) .build(); @@ -154,7 +156,7 @@ public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotI Long memberId = jwtTokenProvider.getMemberId(request); - Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); + memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Page roadPage = roadRepository.findAllBySpot_Id(spotId, PageRequest.of(pageNum, 1)); @@ -174,6 +176,7 @@ public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotI .roadType(road.getRoadType()) .spotId(road.getSpot().getId()) .memberId(road.getMember().getId()) + .memberName(road.getMember().getNickname()) .name(road.getName()) .roadCoordinateDoubleList(roadCoordinateDoubleList) .build(); @@ -212,6 +215,7 @@ public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long stor .roadType(road.getRoadType()) .storeId(road.getStore().getId()) .memberId(road.getMember().getId()) + .memberName(road.getMember().getNickname()) .name(road.getName()) .roadCoordinateDoubleList(roadCoordinateDoubleList) .build(); diff --git a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java index 5ddcdbf7..df3310bf 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/request/CreateRoadRequestDto.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.road.dto.request; import com.ttubeog.domain.road.domain.RoadType; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.Getter; @@ -10,14 +11,27 @@ @Getter public class CreateRoadRequestDto { + @Schema(description = "길 종류", defaultValue = "SPOT") private RoadType roadType; + @Schema(description = "산책스팟 ID", defaultValue = "1") private Long spotId; + @Schema(description = "매장 ID", defaultValue = "1") private Long storeId; + @Schema(description = "길 이름", defaultValue = "스티브의 길") private String name; + @Schema(description = "좌표 포인트 배열", defaultValue = "[\n" + + "[37.50286865234375, 126.95667670044992],\n" + + "[37.5029296875, 126.95677684301509],\n" + + "[37.5030517578125, 126.9568895358081],\n" + + "[37.503204345703125, 126.95712283976323],\n" + + "[37.503173828125, 126.95706043328734],\n" + + "[37.503143310546875, 126.95698617501382],\n" + + "[37.503204345703125, 126.95701685426971]\n" + + "]") private List> roadCoordinateList; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java index 70733b3c..3b572d20 100644 --- a/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java +++ b/src/main/java/com/ttubeog/domain/road/dto/response/RoadResponseDto.java @@ -1,10 +1,7 @@ package com.ttubeog.domain.road.dto.response; -import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.road.domain.RoadType; -import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; -import com.ttubeog.domain.spot.domain.Spot; -import com.ttubeog.domain.store.domain.Store; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import lombok.Getter; @@ -16,18 +13,36 @@ @Builder public class RoadResponseDto { + @Schema(description = "길 ID", defaultValue = "1") private Long id; + @Schema(description = "길 종류", defaultValue = "SPOT") private RoadType roadType; + @Schema(description = "산책스팟 ID", defaultValue = "1") private Long spotId; + @Schema(description = "매장 ID", defaultValue = "1") private Long storeId; + @Schema(description = "멤버 ID", defaultValue = "1") private Long memberId; + @Schema(description = "멤버 이름", defaultValue = "스티브") + private String memberName; + + @Schema(description = "길 이름", defaultValue = "1") private String name; + @Schema(description = "좌표 포인트 배열", defaultValue = "[\n" + + "[37.50286865234375, 126.95667670044992],\n" + + "[37.5029296875, 126.95677684301509],\n" + + "[37.5030517578125, 126.9568895358081],\n" + + "[37.503204345703125, 126.95712283976323],\n" + + "[37.503173828125, 126.95706043328734],\n" + + "[37.503143310546875, 126.95698617501382],\n" + + "[37.503204345703125, 126.95701685426971]\n" + + "]") private List> roadCoordinateDoubleList; -} +} \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index 7dba249a..d913cd7a 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -83,7 +83,7 @@ public ResponseEntity createRoad( content = { @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = RoadRepository.class)) + array = @ArraySchema(schema = @Schema(implementation = RoadResponseDto.class)) ) } ), @@ -126,7 +126,7 @@ public ResponseEntity findRoadBySpotId( content = { @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = RoadRepository.class)) + array = @ArraySchema(schema = @Schema(implementation = RoadResponseDto.class)) ) } ), From ec697c22e72acb25dd72910cade4b4af6a36d105 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 18 Feb 2024 21:15:55 +0900 Subject: [PATCH 320/356] =?UTF-8?q?[Chore]=20Image=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EC=84=A4=EB=AA=85=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 --- .../image/dto/response/ImageResponseDto.java | 10 +++ .../image/presentation/ImageController.java | 73 ++++++++++++++++--- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java index e7593f33..bd12e3a1 100644 --- a/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java +++ b/src/main/java/com/ttubeog/domain/image/dto/response/ImageResponseDto.java @@ -1,6 +1,7 @@ package com.ttubeog.domain.image.dto.response; import com.ttubeog.domain.image.domain.ImageType; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -13,10 +14,19 @@ @NoArgsConstructor public class ImageResponseDto { + @Schema(description = "이미지 ID", defaultValue = "1") public Long id; + + @Schema(description = "랜덤 고유 식별자", defaultValue = "100") public String uuid; + + @Schema(description = "이미지", defaultValue = "url") public String image; + + @Schema(description = "이미지 타입", defaultValue = "SPOT") public ImageType imageType; + + @Schema(description = "장소 ID", defaultValue = "1") public Long placeId; } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index c02bda4e..50d8d145 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -1,7 +1,17 @@ package com.ttubeog.domain.image.presentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; import com.ttubeog.domain.image.application.ImageService; +import com.ttubeog.domain.image.dto.response.ImageResponseDto; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.ErrorResponse; +import com.ttubeog.global.payload.Message; +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.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -21,8 +31,13 @@ public class ImageController { private final ImageService imageService; + @Operation(summary = "산책스팟 이미지 저장", description = "산책스팟의 이미지를 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 저장 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 저장 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) +// @ResponseStatus(value = HttpStatus.CREATED) @PostMapping(value = "/spot", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createSpotImage( @CurrentUser HttpServletRequest request, @RequestParam Long spotId, @@ -31,8 +46,13 @@ public ResponseEntity createSpotImage( return imageService.createSpotImage(request, spotId, fileList); } + @Operation(summary = "매장 이미지 저장", description = "매장의 이미지를 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 저장 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 저장 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @PostMapping(value = "/store", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(value = HttpStatus.CREATED) +// @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createStoreImage( @CurrentUser HttpServletRequest request, @RequestParam Long storeId, @@ -41,8 +61,13 @@ public ResponseEntity createStoreImage( return imageService.createStoreImage(request, storeId, fileList); } + @Operation(summary = "방명록 이미지 저장", description = "방명록의 이미지를 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 저장 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 저장 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @PostMapping(value = "/guestbook", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(value = HttpStatus.CREATED) +// @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createGuestBookImage( @CurrentUser HttpServletRequest request, @RequestParam Long guestBookId, @@ -51,8 +76,13 @@ public ResponseEntity createGuestBookImage( return imageService.createGuestBookImage(request, guestBookId, fileList); } + @Operation(summary = "산책스팟 이미지 조회", description = "산책스팟ID로 해당 이미지를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @GetMapping(value = "/{spotId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageBySpotId( @CurrentUser HttpServletRequest request, @RequestParam Long spotId @@ -60,8 +90,13 @@ public ResponseEntity findImageBySpotId( return imageService.findImageBySpotId(request, spotId); } + @Operation(summary = "매장 이미지 조회", description = "매장ID로 해당 이미지를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @GetMapping(value = "/{storeId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByStoreId( @CurrentUser HttpServletRequest request, @RequestParam Long storeId @@ -69,8 +104,13 @@ public ResponseEntity findImageByStoreId( return imageService.findImageByStoreId(request, storeId); } + @Operation(summary = "방명록 이미지 조회", description = "방명록ID로 해당 이미지를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @GetMapping(value = "/{guestBookId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByGuestBookId( @CurrentUser HttpServletRequest request, @RequestParam Long guestBookId @@ -79,24 +119,39 @@ public ResponseEntity findImageByGuestBookId( } + @Operation(summary = "산책스팟 이미지 삭제", description = "산책스팟의 이미지를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @DeleteMapping(value = "/{spotId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageBySpotId( @RequestParam Long spotId ) { return imageService.deleteImageBySpotId(spotId); } + @Operation(summary = "매장 이미지 삭제", description = "매장의 이미지를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @DeleteMapping(value = "/{storeId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByStoreId( @RequestParam Long storeId ) { return imageService.deleteImageByStoreId(storeId); } + @Operation(summary = "방명록 이미지 삭제", description = "방명록의 이미지를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) @DeleteMapping(value = "/{guestBookId}") - @ResponseStatus(value = HttpStatus.OK) +// @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByGuestBookId( @RequestParam Long guestBookId ) { From 7c13da35751ea89a1163a2d211c007e4c34b7345 Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 19 Feb 2024 00:20:05 +0900 Subject: [PATCH 321/356] =?UTF-8?q?[Chore]=20spot=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20image=20=EB=B0=9B=EC=95=84=EC=98=A4=EA=B8=B0=20?= =?UTF-8?q?=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index e8ada49c..82ce67f0 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -31,7 +31,7 @@ public class CreateSpotRequestDto { @Schema(description = "경도", defaultValue = "126.9275718") private Double longitude; - @Schema(description = "이미지 리스트") - private List image; + // @Schema(description = "이미지 리스트") + // private List image; } From 34b39984ef25f9b81a967049438ae02fa364b44c Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Mon, 19 Feb 2024 00:20:36 +0900 Subject: [PATCH 322/356] =?UTF-8?q?[Chore]=20spot=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20image=20=EB=B0=9B=EC=95=84=EC=98=A4=EA=B8=B0=20?= =?UTF-8?q?=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/application/SpotService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 3e6d3565..6791236e 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -90,9 +90,9 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques } // 산책 스팟 이미지가 1~10개 사이인지 체크 - if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { - throw new InvalidImageListSizeException(); - } + // if (createSpotRequestDto.getImage().isEmpty() || createSpotRequestDto.getImage().size() > 10) { + // throw new InvalidImageListSizeException(); + // } // 산책 스팟 저장 Spot spot = Spot.builder() From e12cd27cf3cfc69e16698542cc75a30a2dffb2f1 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 19 Feb 2024 00:27:14 +0900 Subject: [PATCH 323/356] =?UTF-8?q?[Chore]=20Exception=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/store/exception/UnathorizedMemberException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java index 645d6234..e9b13aa6 100644 --- a/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java +++ b/src/main/java/com/ttubeog/domain/store/exception/UnathorizedMemberException.java @@ -3,6 +3,6 @@ public class UnathorizedMemberException extends RuntimeException { public UnathorizedMemberException() { - super("해당 매장에 대한 수정 권한이 없습니다."); + super("해당 매장에 대한 수정 및 삭제 권한이 없습니다."); } } From de64185e0d2d0465690f896e6a1c4e91f0eb8579 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 19 Feb 2024 00:29:14 +0900 Subject: [PATCH 324/356] =?UTF-8?q?[Feat]=20=EB=A7=A4=EC=9E=A5=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C,=20=EC=A2=8C=ED=91=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/RoadRepository.java | 2 ++ .../repository/RoadCoordinateRepository.java | 4 ++++ .../store/application/StoreService.java | 20 ++++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java index 125bc905..a4e41646 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java +++ b/src/main/java/com/ttubeog/domain/road/domain/repository/RoadRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository @@ -21,4 +22,5 @@ public interface RoadRepository extends JpaRepository { Page findAllByStore_Id(Long storeId, PageRequest pageRequest); + List findByStore(Store store); } diff --git a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java index c9ade995..678091dc 100644 --- a/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java +++ b/src/main/java/com/ttubeog/domain/roadcoordinate/domain/repository/RoadCoordinateRepository.java @@ -1,9 +1,13 @@ package com.ttubeog.domain.roadcoordinate.domain.repository; +import com.ttubeog.domain.road.domain.Road; import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface RoadCoordinateRepository extends JpaRepository { + List findByRoad(Road road); } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 8c73d6a9..ee0af7a7 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -14,6 +14,10 @@ import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; +import com.ttubeog.domain.road.domain.Road; +import com.ttubeog.domain.road.domain.repository.RoadRepository; +import com.ttubeog.domain.roadcoordinate.domain.RoadCoordinate; +import com.ttubeog.domain.roadcoordinate.domain.repository.RoadCoordinateRepository; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; @@ -49,6 +53,9 @@ public class StoreService { private final MemberBenefitRepository memberBenefitRepository; private final GuestBookRepository guestBookRepository; private final LikesRepository likesRepository; + private final RoadRepository roadRepository; + private final RoadCoordinateRepository roadCoordinateRepository; + private final JwtTokenProvider jwtTokenProvider; // 매장 등록 @@ -183,12 +190,19 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { List images = imageRepository.findByStoreId(storeId); imageRepository.deleteAll(images); - // TODO 해당 매장과 연관된 경로 삭제 - // TODO 해당 매장과 연관된 저장경로 삭제 + // 특정 경로와 연관된 좌표 삭제 + List roadsToDelete = roadRepository.findByStore(store); + for (Road road : roadsToDelete) { + List roadCoordinates = roadCoordinateRepository.findByRoad(road); + roadCoordinateRepository.deleteAll(roadCoordinates); + } + + // 해당 매장과 연관된 경로 삭제 + List roads = roadRepository.findByStore(store); + roadRepository.deleteAll(roads); storeRepository.delete(store); - ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) From d9848ddac26c77ad1c4fe465868ae98ffe8f9721 Mon Sep 17 00:00:00 2001 From: Jeongmin39 <80705450+Jeongmin39@users.noreply.github.com> Date: Mon, 19 Feb 2024 02:28:55 +0900 Subject: [PATCH 325/356] =?UTF-8?q?[Chore]=20ImageController=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/image/presentation/ImageController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index 50d8d145..50774d38 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -26,7 +26,7 @@ @Tag(name = "Image", description = "Image API(이미지 API)") @RequiredArgsConstructor @RestController -@RequestMapping("api/v1/image") +@RequestMapping("/api/v1/image") public class ImageController { private final ImageService imageService; From 59fe23804876da8ebd1756ab246f58fec43fda9d Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Mon, 19 Feb 2024 03:50:31 +0900 Subject: [PATCH 326/356] =?UTF-8?q?[Chore]=20ImageService=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/image/application/ImageService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index d2704508..6ff8cd9d 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -68,7 +68,7 @@ public ResponseEntity createSpotImage(HttpServletRequest request, Long spotId .spot(spot) .build(); - String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateStoreKeyName(image), multipartFile); + String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateSpotKeyName(image), multipartFile); image.updateImageUrl(imageUrl); Image savedImage = imageRepository.save(image); @@ -149,7 +149,7 @@ public ResponseEntity createGuestBookImage(HttpServletRequest request, Long g .guestBook(guestBook) .build(); - String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateStoreKeyName(image), multipartFile); + String imageUrl = amazonS3Manager.uploadFile(amazonS3Manager.generateGuestBookKeyName(image), multipartFile); image.updateImageUrl(imageUrl); Image savedImage = imageRepository.save(image); From 566237df4026d2b02281600d69e575533aa11798 Mon Sep 17 00:00:00 2001 From: Jeongmin39 <80705450+Jeongmin39@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:41:01 +0900 Subject: [PATCH 327/356] =?UTF-8?q?[Fix]=20=EB=B0=A9=EB=AA=85=EB=A1=9D=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/presentation/GuestBookController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 5a77c044..24a8fdb0 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -62,7 +62,7 @@ public class GuestBookController { @ResponseStatus(value = HttpStatus.CREATED) public ResponseEntity createGuestBook( @CurrentUser HttpServletRequest request, - @RequestPart CreateGuestBookRequestDto createGuestBookRequestDto + @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto ) throws JsonProcessingException { return guestBookService.createGuestBook(request, createGuestBookRequestDto); } From 1e611febc32093d2832a5ceca3b6c3ccbe29032e Mon Sep 17 00:00:00 2001 From: choeun7 Date: Mon, 4 Mar 2024 23:04:52 +0900 Subject: [PATCH 328/356] =?UTF-8?q?[Refactor]=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Service 단에 무의미한 반복이 많아서, ApiResponse를 반환하는 방법으로 바꿨습니다. Benefit 파일만 우선 예시로 수정했습니다. --- .../benefit/application/BenefitService.java | 27 +++++-------------- .../presentation/BenefitController.java | 6 ++--- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 74f39940..38de8493 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -41,7 +41,7 @@ public class BenefitService { //게임 성공 후 혜택 저장 @Transactional - public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + public ApiResponse saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); @@ -73,18 +73,13 @@ public ResponseEntity saveBenefit(HttpServletRequest request, Long benefitId) .createdAt(memberBenefit.getCreatedAt()) .build(); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(saveBenefitRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new ApiResponse(true, saveBenefitRes); } //혜택 사용 @Transactional - public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + public ApiResponse useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); @@ -112,16 +107,11 @@ public ResponseEntity useBenefit(HttpServletRequest request, Long benefitId) .type(benefit.getType()) .build(); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(saveBenefitRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new ApiResponse(true, saveBenefitRes); } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { + public ApiResponse findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -141,12 +131,7 @@ public ResponseEntity findMyBenefit(HttpServletRequest request, Integer page) .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(saveBenefitRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new ApiResponse(true, saveBenefitRes); } //한달지나면 expired true로 만들기 diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 88b7a03a..8f122153 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -34,7 +34,7 @@ public ResponseEntity saveBenefit( HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.saveBenefit(request, benefitId); + return ResponseEntity.ok(benefitService.saveBenefit(request, benefitId)); } //혜택 사용 @@ -48,7 +48,7 @@ public ResponseEntity useBenefit( HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { - return benefitService.useBenefit(request, benefitId); + return ResponseEntity.ok(benefitService.useBenefit(request, benefitId)); } //혜택 조회 @@ -62,6 +62,6 @@ public ResponseEntity findMyBenefit( HttpServletRequest request, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { - return benefitService.findMyBenefit(request, page); + return ResponseEntity.ok(benefitService.findMyBenefit(request, page)); } } From 62d65679960dcd8ddfd8b77a9152a461207b1c45 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Thu, 7 Mar 2024 01:54:24 +0900 Subject: [PATCH 329/356] =?UTF-8?q?[Docs]=20Swagger=20=EB=82=B4=EC=9A=A9?= =?UTF-8?q?=20=EB=B3=B4=EC=B6=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/presentation/StoreController.java | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 50837858..46d65b05 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.store.presentation; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.benefit.application.BenefitService; import com.ttubeog.domain.game.application.GameService; import com.ttubeog.domain.game.dto.response.FindGameRes; import com.ttubeog.domain.likes.application.LikesService; @@ -36,10 +35,15 @@ public class StoreController { private final GameService gameService; - // 매장 등록 + /** + * 매장 등록 API + * @param request 유저 검증 + * @param registerStoreReq 매장 등록 DTO + * @return ApiResponse (check: true, information: registerStoreRes) + */ @Operation(summary = "매장 등록", description = "매장을 등록합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "매장 등록 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = RegisterStoreRes.class))}), + @ApiResponse(responseCode = "200", description = "OK", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = RegisterStoreRes.class))}), @ApiResponse(responseCode = "400", description = "매장 등록 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping @@ -50,10 +54,15 @@ public ResponseEntity registerStore( return storeService.registerStore(request, registerStoreReq); } - // 매장 수정 + /** + * 매장 수정 API + * @param request 유저 검증 + * @param updateStoreReq 매장 수정 DTO + * @return ApiResponse (check: true, information: updateStoreRes) + */ @Operation(summary = "매장 수정", description = "매장 정보를 수정합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "매장 수정 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateStoreRes.class))}), + @ApiResponse(responseCode = "200", description = "OK", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UpdateStoreRes.class))}), @ApiResponse(responseCode = "400", description = "매장 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PatchMapping @@ -64,10 +73,15 @@ public ResponseEntity updateStore( return storeService.updateStore(request, updateStoreReq); } - // 매장 삭제 + /** + * 매장 삭제 API + * @param request 유저 검증 + * @param storeId 매장 ID + * @return ApiResponse (check: true, information: message) + */ @Operation(summary = "매장 삭제", description = "매장 정보를 삭제합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "매장 삭제 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "200", description = "OK", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @ApiResponse(responseCode = "400", description = "매장 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @DeleteMapping("/{storeId}") @@ -78,10 +92,15 @@ public ResponseEntity deleteStore( return storeService.deleteStore(request, storeId); } - // 매장 세부사항 조회 + /** + * 매장 세부사항 조회 API + * @param request 유저검증 + * @param storeId 매장 ID + * @return ApiResponse (check: true, information: getStoreDetailRes) + */ @Operation(summary = "매장 세부사항 조회", description = "매장 세부사항을 조회합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "매장 세부사항 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetStoreDetailRes.class))}), + @ApiResponse(responseCode = "200", description = "매장 ", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetStoreDetailRes.class))}), @ApiResponse(responseCode = "400", description = "매장 세부사항 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/{storeId}") @@ -92,7 +111,12 @@ public ResponseEntity getStoreDetails( return storeService.getStoreDetails(request, storeId); } - // 매장 좋아요 누르기 + /** + * 매장 좋아요 누르기 API + * @param request 유저 검증 + * @param storeId 매장 ID + * @return ApiResponse (check: true, information: message) + */ @Operation(summary = "매장 좋아요 누르기", description = "매장에 대한 좋아요를 누릅니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "매장 좋아요 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @@ -106,7 +130,13 @@ public ResponseEntity likesStore( return likesService.likesStore(request, storeId); } - //StoreId로 매장, 혜택 조회 + /** + * 매장 혜택 조회 API + * @param request 유저 검증 + * @param storeId 매장 ID + * @return ApiResponse (check: true, information: findGameRes) + * @throws JsonProcessingException JSON Processing 에러 + */ @Operation(summary = "매장으로 게임, 혜택 조회", description = "매장ID에 해당하는 모든 게임과 해당 혜택을 조회합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "게임 조회 누르기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = FindGameRes.class))}), From f2ee9fa62eda649af429cecdba5a7424e6074d4f Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 10 Mar 2024 19:27:04 +0900 Subject: [PATCH 330/356] =?UTF-8?q?[Refactor]=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ApiResponse -> CommonDto swagger의 @ApiResponse와 겹쳐서 클래스명 수정했습니다. --- .../benefit/application/BenefitService.java | 15 ++++---- .../presentation/BenefitController.java | 7 ++-- .../comment/application/CommentService.java | 38 +++++-------------- .../presentation/CommentController.java | 17 +++++---- .../domain/game/application/GameService.java | 22 +++++------ .../application/GuestBookService.java | 13 +++---- .../image/application/ImageService.java | 26 +++++-------- .../likes/application/LikesService.java | 6 +-- .../member/application/MemberService.java | 21 +++++----- .../member/presentation/MemberController.java | 3 +- .../place/application/PlaceService.java | 12 +++--- .../domain/road/application/RoadService.java | 10 ++--- .../domain/spot/application/SpotService.java | 10 ++--- .../store/application/StoreService.java | 10 ++--- .../global/error/ApiControllerAdvice.java | 18 ++++----- .../{ApiResponse.java => CommonDto.java} | 4 +- 16 files changed, 101 insertions(+), 131 deletions(-) rename src/main/java/com/ttubeog/global/payload/{ApiResponse.java => CommonDto.java} (87%) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 38de8493..e1e21707 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -15,12 +15,11 @@ import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -41,7 +40,7 @@ public class BenefitService { //게임 성공 후 혜택 저장 @Transactional - public ApiResponse saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + public CommonDto saveBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); @@ -73,13 +72,13 @@ public ApiResponse saveBenefit(HttpServletRequest request, Long benefitId) throw .createdAt(memberBenefit.getCreatedAt()) .build(); - return new ApiResponse(true, saveBenefitRes); + return new CommonDto(true, saveBenefitRes); } //혜택 사용 @Transactional - public ApiResponse useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { + public CommonDto useBenefit(HttpServletRequest request, Long benefitId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Benefit benefit = benefitRepository.findById(benefitId).orElseThrow(NonExistentBenefitException::new); @@ -107,11 +106,11 @@ public ApiResponse useBenefit(HttpServletRequest request, Long benefitId) throws .type(benefit.getType()) .build(); - return new ApiResponse(true, saveBenefitRes); + return new CommonDto(true, saveBenefitRes); } //혜택 조회(사용 가능, 사용 완료, 만료 혜택 모두 조회) - public ApiResponse findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { + public CommonDto findMyBenefit(HttpServletRequest request, Integer page) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -131,7 +130,7 @@ public ApiResponse findMyBenefit(HttpServletRequest request, Integer page) throw .build() ).toList(); - return new ApiResponse(true, saveBenefitRes); + return new CommonDto(true, saveBenefitRes); } //한달지나면 expired true로 만들기 diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 8f122153..f1b7dcd3 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.ttubeog.domain.benefit.application.BenefitService; import com.ttubeog.domain.benefit.dto.response.SaveBenefitRes; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -30,7 +31,7 @@ public class BenefitController { @ApiResponse(responseCode = "400", description = "혜택 저장 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PatchMapping("/{benefitId}") - public ResponseEntity saveBenefit( + public ResponseEntity saveBenefit( HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -44,7 +45,7 @@ public ResponseEntity saveBenefit( @ApiResponse(responseCode = "400", description = "혜택 사용 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PatchMapping("{benefitId}/use") - public ResponseEntity useBenefit( + public ResponseEntity useBenefit( HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId ) throws JsonProcessingException { @@ -58,7 +59,7 @@ public ResponseEntity useBenefit( @ApiResponse(responseCode = "400", description = "혜택 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @GetMapping - public ResponseEntity findMyBenefit( + public ResponseEntity findMyBenefit( HttpServletRequest request, @RequestParam(name = "page") Integer page ) throws JsonProcessingException { diff --git a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java index d24168ca..1714ebda 100644 --- a/src/main/java/com/ttubeog/domain/comment/application/CommentService.java +++ b/src/main/java/com/ttubeog/domain/comment/application/CommentService.java @@ -14,7 +14,7 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -36,7 +36,7 @@ public class CommentService { // 댓글 작성 @Transactional - public ResponseEntity writeComment(HttpServletRequest request, WriteCommentReq writeCommentReq) { + public CommonDto writeComment(HttpServletRequest request, WriteCommentReq writeCommentReq) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -58,17 +58,12 @@ public ResponseEntity writeComment(HttpServletRequest request, WriteCommentRe .longitude(comment.getLongitude()) .build(); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(writeCommentRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, writeCommentRes); } // 댓글 수정 @Transactional - public ResponseEntity updateComment(HttpServletRequest request, UpdateCommentReq updateCommentReq) { + public CommonDto updateComment(HttpServletRequest request, UpdateCommentReq updateCommentReq) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -86,29 +81,19 @@ public ResponseEntity updateComment(HttpServletRequest request, UpdateComment .content(comment.getContent()) .build(); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(updateCommentRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, updateCommentRes); } // 댓글 삭제 @Transactional - public ResponseEntity deleteComment(HttpServletRequest request, Long commentId) { + public CommonDto deleteComment(HttpServletRequest request, Long commentId) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Comment comment = commentRepository.findById(commentId).orElseThrow(NonExistentCommentException::new); commentRepository.delete(comment); - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(Message.builder().message("댓글이 정상적으로 삭제되었습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("댓글이 정상적으로 삭제되었습니다.").build()); } public List getAllComments() { @@ -116,7 +101,7 @@ public List getAllComments() { } // AR뷰를 위한 댓글 조회 - public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { + public CommonDto getCommentForAR(GetCommentReq getCommentReq) { Double userLatitude = getCommentReq.getLatitude(); Double userLongitude = getCommentReq.getLongitude(); @@ -144,12 +129,7 @@ public ResponseEntity getCommentForAR(GetCommentReq getCommentReq) { } } - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(showComments) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, showComments); } // 거리 계산 diff --git a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java index b6b6e7e3..f323a285 100644 --- a/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/ttubeog/domain/comment/presentation/CommentController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.comment.dto.response.GetCommentRes; import com.ttubeog.domain.comment.dto.response.UpdateCommentRes; import com.ttubeog.domain.comment.dto.response.WriteCommentRes; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -36,11 +37,11 @@ public class CommentController { @ApiResponse(responseCode = "400", description = "댓글 작성 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping - public ResponseEntity writeComment( + public ResponseEntity writeComment( HttpServletRequest request, @Valid @RequestBody WriteCommentReq writeCommentReq ) { - return commentService.writeComment(request, writeCommentReq); + return ResponseEntity.ok(commentService.writeComment(request, writeCommentReq)); } // 댓글 수정 @@ -50,11 +51,11 @@ public ResponseEntity writeComment( @ApiResponse(responseCode = "400", description = "댓글 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PatchMapping - public ResponseEntity updateComment( + public ResponseEntity updateComment( HttpServletRequest request, @Valid @RequestBody UpdateCommentReq updateCommentReq ) { - return commentService.updateComment(request, updateCommentReq); + return ResponseEntity.ok(commentService.updateComment(request, updateCommentReq)); } // 댓글 삭제 @@ -64,11 +65,11 @@ public ResponseEntity updateComment( @ApiResponse(responseCode = "400", description = "댓글 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @DeleteMapping("/{commentId}") - public ResponseEntity deleteComment( + public ResponseEntity deleteComment( HttpServletRequest request, @PathVariable Long commentId ) { - return commentService.deleteComment(request, commentId); + return ResponseEntity.ok(commentService.deleteComment(request, commentId)); } // AR뷰 댓글 조회 (반경 이용) @@ -78,9 +79,9 @@ public ResponseEntity deleteComment( @ApiResponse(responseCode = "400", description = "댓글 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping - public ResponseEntity getCommentForAR( + public ResponseEntity getCommentForAR( @Valid GetCommentReq getCommentReq ) { - return commentService.getCommentForAR(getCommentReq); + return ResponseEntity.ok(commentService.getCommentForAR(getCommentReq)); } } diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 0e9eaa8e..8bb8f0dd 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -19,7 +19,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -93,7 +93,7 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr .benefitContent(benefit.getContent()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(createGiftRes) .build(); @@ -149,7 +149,7 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask .benefitContent(benefit.getContent()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(createBasketballRes) .build(); @@ -207,7 +207,7 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet .options(rouletteGame.getOptions()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(createRouletteRes) .build(); @@ -250,7 +250,7 @@ public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq up .benefitType(newBenefit.getType()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(updateGiftRes) .build(); @@ -296,7 +296,7 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask .benefitType(newBenefit.getType()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(updateBasketballRes) .build(); @@ -347,7 +347,7 @@ public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRoulet .benefits(benefitResDtoList) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(updateRouletteRes) .build(); @@ -369,7 +369,7 @@ public ResponseEntity deleteGame(HttpServletRequest request, Long gameId) thr gameRepository.delete(game); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("게임을 삭제했습니다.").build()) .build(); @@ -409,7 +409,7 @@ public ResponseEntity findGame(HttpServletRequest request, Long gameId) throw FindGameRes findGameRes = builder.build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(findGameRes) .build(); @@ -433,7 +433,7 @@ public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) th .build()) .collect(Collectors.toList()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(benefitResDtoList) .build(); @@ -483,7 +483,7 @@ public ResponseEntity findByStore(HttpServletRequest request, Long storeId) t findGameResList.add(findGameRes); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(findGameResList) .build(); diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 25a18311..ec20a499 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.guestbook.application; -import com.ttubeog.domain.UuidImage.domain.UuidImage; import com.ttubeog.domain.UuidImage.domain.repository.UuidImageRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.aws.s3.AmazonS3Manager; @@ -21,7 +20,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; @@ -32,9 +31,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; -import java.util.UUID; @RequiredArgsConstructor @Service @@ -85,7 +82,7 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { throw new InvalidGuestBookException(); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(guestBookResponseDto) .build(); @@ -191,7 +188,7 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(guestBookResponseDtoList) .build(); @@ -222,7 +219,7 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(guestBookResponseDtoList) .build(); @@ -248,7 +245,7 @@ public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestB //imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("방명록을 삭제했습니다").build()) .build(); diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index d2704508..bd887566 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -4,15 +4,10 @@ import com.ttubeog.domain.aws.s3.AmazonS3Manager; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; -import com.ttubeog.domain.guestbook.exception.InvalidGuestBookIdException; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; -import com.ttubeog.domain.image.dto.request.UpdateImageRequestDto; import com.ttubeog.domain.image.dto.response.ImageResponseDto; -import com.ttubeog.domain.image.exception.InvalidImageException; -import com.ttubeog.domain.image.exception.InvalidImageTypeException; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.domain.Spot; @@ -21,7 +16,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -29,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @@ -82,7 +76,7 @@ public ResponseEntity createSpotImage(HttpServletRequest request, Long spotId }).collect(Collectors.toList()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -122,7 +116,7 @@ public ResponseEntity createStoreImage(HttpServletRequest request, Long store .build(); }).collect(Collectors.toList()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -162,7 +156,7 @@ public ResponseEntity createGuestBookImage(HttpServletRequest request, Long g .build(); }).collect(Collectors.toList()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -191,7 +185,7 @@ public ResponseEntity findImageBySpotId(HttpServletRequest request, Long spot .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -220,7 +214,7 @@ public ResponseEntity findImageByStoreId(HttpServletRequest request, Long sto .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -249,7 +243,7 @@ public ResponseEntity findImageByGuestBookId(HttpServletRequest request, Long .build() ).toList(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(imageResponseDtoList) .build(); @@ -266,7 +260,7 @@ public ResponseEntity deleteImageBySpotId(Long spotId) { List imageList = imageRepository.findAllBySpot(spot); imageRepository.deleteAll(imageList); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information("정상적으로 삭제되었습니다.") .build(); @@ -283,7 +277,7 @@ public ResponseEntity deleteImageByStoreId(Long storeId) { List imageList = imageRepository.findAllByStore(store); imageRepository.deleteAll(imageList); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information("정상적으로 삭제되었습니다.") .build(); @@ -300,7 +294,7 @@ public ResponseEntity deleteImageByGuestBookId(Long guestBookId) { List imageList = imageRepository.findAllByGuestBook(guestBook); imageRepository.deleteAll(imageList); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information("정상적으로 삭제되었습니다.") .build(); diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index 267134e4..a79527b0 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -13,7 +13,7 @@ import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.domain.spot.exception.NonExistentSpotException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -52,7 +52,7 @@ public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { likesRepository.save(likes); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("매장에 대한 좋아요를 눌렀습니다.").build()) .build(); @@ -79,7 +79,7 @@ public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { likesRepository.save(likes); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.").build()) .build(); diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index cb7489fd..498e0658 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -20,7 +20,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.DefaultAssert; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -34,7 +34,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; @RequiredArgsConstructor @Service @@ -64,7 +63,7 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { .platform(member.getPlatform()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(memberDetailDto) .build(); @@ -89,7 +88,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN .nicknameChanged(checkMember.getNicknameChange()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(false) .information(memberNicknameDto) .build(); @@ -114,7 +113,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN .nicknameChanged(member.getNicknameChange()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(memberNicknameDto) .build(); @@ -129,7 +128,7 @@ public ResponseEntity postMemberNicknameCheck(HttpServletRequest request, Pro Boolean isNicknameUsed = memberRepository.existsByNickname(produceNicknameRequest.getNickname()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(!isNicknameUsed) .information("닉네임 중복이면 check -> false, 중복이 아니면 check -> true") .build(); @@ -163,7 +162,7 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { OAuthTokenResponse oAuthTokenResponse = new OAuthTokenResponse(newAccessToken, newRefreshToken, member.isRegisteredOAuthMember()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(oAuthTokenResponse) .build(); @@ -179,7 +178,7 @@ public ResponseEntity deleteLogout(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); deleteValueByKey(String.valueOf(memberId)); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("성공적으로 로그아웃 되었습니다.").build()) .build(); @@ -216,7 +215,7 @@ public ResponseEntity deleteUser(HttpServletRequest request) { memberRepository.save(member); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()) .build(); @@ -260,7 +259,7 @@ public ResponseEntity getMySpotList(HttpServletRequest request, Integer pageN memberPlaceDtoList.add(memberPlaceDto); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(memberPlaceDtoList) .build(); @@ -287,7 +286,7 @@ public ResponseEntity getMyStoreList(HttpServletRequest request, Integer page memberPlaceDtoList.add(memberPlaceDto); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(memberPlaceDtoList) .build(); diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index 7ac0ecf0..b3eb58a5 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -9,6 +9,7 @@ import com.ttubeog.domain.member.dto.response.MemberPlaceDto; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -61,7 +62,7 @@ public ResponseEntity postMemberNickname( @Operation(summary = "닉네임 중복 확인", description = "닉네임의 중복을 확인합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "닉네임 설정 가능", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = com.ttubeog.global.payload.ApiResponse.class))}), + @ApiResponse(responseCode = "200", description = "닉네임 설정 가능", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = CommonDto.class))}), @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname/check") diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index 89f712b4..de9bfe41 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -20,7 +20,7 @@ import com.ttubeog.domain.spot.domain.repository.SpotRepository; import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; @@ -171,7 +171,7 @@ public ResponseEntity getAllPlaces(HttpServletRequest request, Pageable pagea List allPlaces = getAllPlaceResList(request, pageable); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(allPlaces) .build(); @@ -226,7 +226,7 @@ public ResponseEntity getAllPlacesRecommended(HttpServletRequest request, Pag allPlaces.sort(Comparator.comparingInt(GetAllPlaceRes::getRecommendationScore).reversed()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(allPlaces) .build(); @@ -268,7 +268,7 @@ public ResponseEntity getAllPlacesNearby(HttpServletRequest request, GetNearb allPlaces.sort(Comparator.comparingDouble(GetAllPlaceRes::getDistance)); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(allPlaces) .build(); @@ -285,7 +285,7 @@ public ResponseEntity getAllPlacesLatest(HttpServletRequest request, Pageable List allPlaces = getAllPlaceResList(request, pageable); allPlaces.sort(Comparator.comparing(GetAllPlaceRes::getCreatedAt).reversed()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(allPlaces) .build(); @@ -350,7 +350,7 @@ public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq .build()) .collect(Collectors.toList()); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(searchPlaceRes) .build(); diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 0de83330..14af8230 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -20,7 +20,7 @@ import com.ttubeog.domain.store.domain.Store; import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.domain.store.exception.InvalidStoreIdException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -144,7 +144,7 @@ public ResponseEntity createRoad(HttpServletRequest request, CreateRoadReques throw new InvalidRoadTypeException(); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(roadResponseDto) .build(); @@ -183,7 +183,7 @@ public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotI roadResponseDtoList.add(roadResponseDto); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(roadResponseDtoList) .build(); @@ -222,7 +222,7 @@ public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long stor roadResponseDtoList.add(roadResponseDto); } - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(roadResponseDtoList) .build(); @@ -249,7 +249,7 @@ public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { roadCoordinateRepository.deleteAll(roadCoordinateList); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("산책로를 삭제했습니다.").build()) .build(); diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 6791236e..9d9c371b 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -6,9 +6,7 @@ import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; -import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; @@ -24,7 +22,7 @@ import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.domain.spot.exception.InvalidSpotIdException; import com.ttubeog.domain.store.exception.NonExistentStoreException; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; @@ -67,7 +65,7 @@ private ResponseEntity getResponseEntity(Spot spot) { .stars(spot.getStars()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(createSpotResponseDto) .build(); @@ -137,7 +135,7 @@ public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { .isFavorited(isFavorited) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(getSpotDetailRes) .build(); @@ -203,7 +201,7 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { List guestBookList = guestBookRepository.findAllBySpot(spot); guestBookRepository.deleteAll(guestBookList); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("산책 스팟을 삭제햇습니다.").build()) .build(); diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index ee0af7a7..947744af 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -29,7 +29,7 @@ import com.ttubeog.domain.store.exception.UnathorizedMemberException; import com.ttubeog.domain.store.exception.NonExistentStoreException; import com.ttubeog.domain.member.domain.Member; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -98,7 +98,7 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .type(store.getType()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(registerStoreRes) .build(); @@ -145,7 +145,7 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq .type(store.getType()) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(updateStoreRes) .build(); @@ -203,7 +203,7 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { storeRepository.delete(store); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) .build(); @@ -243,7 +243,7 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .isFavorited(isFavorited) .build(); - ApiResponse apiResponse = ApiResponse.builder() + CommonDto apiResponse = CommonDto.builder() .check(true) .information(getStoreDetailRes) .build(); diff --git a/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java b/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java index 7886112d..75933f15 100644 --- a/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java +++ b/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java @@ -1,6 +1,6 @@ package com.ttubeog.global.error; -import com.ttubeog.global.payload.ApiResponse; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorCode; import com.ttubeog.global.payload.ErrorResponse; import org.springframework.http.HttpStatus; @@ -26,7 +26,7 @@ protected ResponseEntity handleHttpRequestMethodNotSupportedException( .clazz(e.getMethod()) .message(e.getMessage()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.METHOD_NOT_ALLOWED); } @@ -42,7 +42,7 @@ public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNot .fieldErrors(e.getFieldErrors()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.OK); } @@ -57,7 +57,7 @@ public ResponseEntity handleInvalidParameterException(InvalidParameterExcepti .fieldErrors(e.getFieldErrors()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.OK); } @@ -73,7 +73,7 @@ protected ResponseEntity handleDefaultException(DefaultException e) { .message(e.toString()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.resolve(errorCode.getStatus())); } @@ -85,7 +85,7 @@ protected ResponseEntity handleException(Exception e) { .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message(e.toString()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @@ -97,7 +97,7 @@ protected ResponseEntity handleAuthenticationException(AuthenticationExceptio .status(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED.value()) .message(e.getMessage()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @@ -108,7 +108,7 @@ protected ResponseEntity handleCustomAuthenticationException(DefaultAuthentic .status(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED.value()) .message(e.getMessage()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @@ -121,7 +121,7 @@ protected ResponseEntity handleNullPointerException(DefaultNullPointerExcepti .message(e.getMessage()) .build(); - ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); } diff --git a/src/main/java/com/ttubeog/global/payload/ApiResponse.java b/src/main/java/com/ttubeog/global/payload/CommonDto.java similarity index 87% rename from src/main/java/com/ttubeog/global/payload/ApiResponse.java rename to src/main/java/com/ttubeog/global/payload/CommonDto.java index 39ce9f70..d4649268 100644 --- a/src/main/java/com/ttubeog/global/payload/ApiResponse.java +++ b/src/main/java/com/ttubeog/global/payload/CommonDto.java @@ -7,7 +7,7 @@ @ToString @Data -public class ApiResponse { +public class CommonDto { @Schema( type = "boolean", example = "true", description="올바르게 로직을 처리했으면 True, 아니면 False를 반환합니다.") private boolean check; @@ -16,7 +16,7 @@ public class ApiResponse { private Object information; @Builder - public ApiResponse(boolean check, Object information) { + public CommonDto(boolean check, Object information) { this.check = check; this.information = information; } From b98b91798b56bfd03571ab4a5d11d7ba0b481841 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Sun, 10 Mar 2024 19:34:36 +0900 Subject: [PATCH 331/356] =?UTF-8?q?[Refactor]=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20=EB=B0=A9=EB=B2=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/application/GameService.java | 90 +++++-------------- .../game/presentation/GameController.java | 37 ++++---- 2 files changed, 39 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/game/application/GameService.java b/src/main/java/com/ttubeog/domain/game/application/GameService.java index 8bb8f0dd..8f1d26fd 100644 --- a/src/main/java/com/ttubeog/domain/game/application/GameService.java +++ b/src/main/java/com/ttubeog/domain/game/application/GameService.java @@ -49,7 +49,7 @@ public class GameService { // 선물게임 생성 @Transactional - public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { + public CommonDto createGift(HttpServletRequest request, CreateGiftReq createGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findByIdAndMember(createGiftReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); @@ -93,17 +93,12 @@ public ResponseEntity createGift(HttpServletRequest request, CreateGiftReq cr .benefitContent(benefit.getContent()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(createGiftRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, createGiftRes); } // 농구게임 생성 @Transactional - public ResponseEntity createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { + public CommonDto createBasketBall(HttpServletRequest request, CreateBasketballReq createBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findByIdAndMember(createBasketballReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); @@ -149,17 +144,12 @@ public ResponseEntity createBasketBall(HttpServletRequest request, CreateBask .benefitContent(benefit.getContent()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(createBasketballRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, createBasketballRes); } //돌림판 게임 생성 @Transactional - public ResponseEntity createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { + public CommonDto createRoulette(HttpServletRequest request, CreateRouletteReq createRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findByIdAndMember(createRouletteReq.getStoreId(), member).orElseThrow(InvalidStoreIdException::new); @@ -207,17 +197,12 @@ public ResponseEntity createRoulette(HttpServletRequest request, CreateRoulet .options(rouletteGame.getOptions()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(createRouletteRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, createRouletteRes); } //선물게임 수정 @Transactional - public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { + public CommonDto updateGift(HttpServletRequest request, UpdateGiftReq updateGiftReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); GiftGame giftGame = giftGameRepository.findById(updateGiftReq.getGameId()).orElseThrow(NonExistentGameException::new); @@ -250,17 +235,12 @@ public ResponseEntity updateGift(HttpServletRequest request, UpdateGiftReq up .benefitType(newBenefit.getType()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(updateGiftRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, updateGiftRes); } //농구게임 수정 @Transactional - public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { + public CommonDto updateBasketball(HttpServletRequest request, UpdateBasketballReq updateBasketballReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); BasketballGame basketballGame = basketBallRepository.findById(updateBasketballReq.getGameId()).orElseThrow(NonExistentGameException::new); @@ -296,17 +276,12 @@ public ResponseEntity updateBasketball(HttpServletRequest request, UpdateBask .benefitType(newBenefit.getType()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(updateBasketballRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, updateBasketballRes); } //돌림판 게임 수정 @Transactional - public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { + public CommonDto updateRoulette(HttpServletRequest request, UpdateRouletteReq updateRouletteReq) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); RouletteGame rouletteGame = rouletteRepository.findById(updateRouletteReq.getGameId()).orElseThrow(NonExistentGameException::new); @@ -347,17 +322,12 @@ public ResponseEntity updateRoulette(HttpServletRequest request, UpdateRoulet .benefits(benefitResDtoList) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(updateRouletteRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, updateRouletteRes); } //게임 삭제 @Transactional - public ResponseEntity deleteGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + public CommonDto deleteGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); @@ -369,17 +339,12 @@ public ResponseEntity deleteGame(HttpServletRequest request, Long gameId) thr gameRepository.delete(game); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("게임을 삭제했습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("게임을 삭제했습니다.").build()); } //게임 조회 @Transactional - public ResponseEntity findGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { + public CommonDto findGame(HttpServletRequest request, Long gameId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentBenefitException::new); @@ -409,17 +374,12 @@ public ResponseEntity findGame(HttpServletRequest request, Long gameId) throw FindGameRes findGameRes = builder.build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(findGameRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, findGameRes); } //게임ID로 혜택 조회 @Transactional - public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) throws JsonProcessingException { + public CommonDto findBenefit(HttpServletRequest request, Long gameId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Game game = gameRepository.findById(gameId).orElseThrow(NonExistentGameException::new); @@ -433,16 +393,11 @@ public ResponseEntity findBenefit(HttpServletRequest request, Long gameId) th .build()) .collect(Collectors.toList()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(benefitResDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, benefitResDtoList); } //매장ID로 게임 조회 - public ResponseEntity findByStore(HttpServletRequest request, Long storeId) throws JsonProcessingException { + public CommonDto findByStore(HttpServletRequest request, Long storeId) throws JsonProcessingException { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); @@ -483,11 +438,6 @@ public ResponseEntity findByStore(HttpServletRequest request, Long storeId) t findGameResList.add(findGameRes); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(findGameResList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, findGameResList); } } diff --git a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java index d0aa8ff5..6d1a06fa 100644 --- a/src/main/java/com/ttubeog/domain/game/presentation/GameController.java +++ b/src/main/java/com/ttubeog/domain/game/presentation/GameController.java @@ -4,6 +4,7 @@ import com.ttubeog.domain.game.application.GameService; import com.ttubeog.domain.game.dto.request.*; import com.ttubeog.domain.game.dto.response.*; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -33,11 +34,11 @@ public class GameController { @ApiResponse(responseCode = "400", description = "선물 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PostMapping("/gift") - public ResponseEntity createGift( + public ResponseEntity createGift( HttpServletRequest request, @Valid @RequestBody CreateGiftReq createGiftReq ) throws JsonProcessingException { - return gameService.createGift(request, createGiftReq); + return ResponseEntity.ok(gameService.createGift(request, createGiftReq)); } //농구 게임 생성 @@ -47,11 +48,11 @@ public ResponseEntity createGift( @ApiResponse(responseCode = "400", description = "농구 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PostMapping("/basketball") - public ResponseEntity createBasketball( + public ResponseEntity createBasketball( HttpServletRequest request, @Valid @RequestBody CreateBasketballReq createBasketballReq ) throws JsonProcessingException { - return gameService.createBasketBall(request, createBasketballReq); + return ResponseEntity.ok(gameService.createBasketBall(request, createBasketballReq)); } //돌림판 게임 생성 @@ -61,11 +62,11 @@ public ResponseEntity createBasketball( @ApiResponse(responseCode = "400", description = "돌림판 게임 생성 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PostMapping("/roulette") - public ResponseEntity createRoulette( + public ResponseEntity createRoulette( HttpServletRequest request, @Valid @RequestBody CreateRouletteReq createRouletteReq ) throws JsonProcessingException { - return gameService.createRoulette(request, createRouletteReq); + return ResponseEntity.ok(gameService.createRoulette(request, createRouletteReq)); } //선물 게임 수정 @@ -75,11 +76,11 @@ public ResponseEntity createRoulette( @ApiResponse(responseCode = "400", description = "선물 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PatchMapping("/gift") - public ResponseEntity updateGift( + public ResponseEntity updateGift( HttpServletRequest request, @Valid @RequestBody UpdateGiftReq updateGiftReq ) throws JsonProcessingException { - return gameService.updateGift(request, updateGiftReq); + return ResponseEntity.ok(gameService.updateGift(request, updateGiftReq)); } //농구 게임 수정 @@ -89,11 +90,11 @@ public ResponseEntity updateGift( @ApiResponse(responseCode = "400", description = "농구 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PatchMapping("/basketball") - public ResponseEntity updateBasketball( + public ResponseEntity updateBasketball( HttpServletRequest request, @Valid @RequestBody UpdateBasketballReq updateBasketballReq ) throws JsonProcessingException { - return gameService.updateBasketball(request, updateBasketballReq); + return ResponseEntity.ok(gameService.updateBasketball(request, updateBasketballReq)); } //돌림판 게임 수정 @@ -103,11 +104,11 @@ public ResponseEntity updateBasketball( @ApiResponse(responseCode = "400", description = "돌림판 게임 수정 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @PatchMapping("/roulette") - public ResponseEntity updateRoulette( + public ResponseEntity updateRoulette( HttpServletRequest request, @Valid @RequestBody UpdateRouletteReq updateRouletteReq ) throws JsonProcessingException { - return gameService.updateRoulette(request, updateRouletteReq); + return ResponseEntity.ok(gameService.updateRoulette(request, updateRouletteReq)); } //게임 삭제 @@ -117,11 +118,11 @@ public ResponseEntity updateRoulette( @ApiResponse(responseCode = "400", description = "삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @DeleteMapping("/{gameId}") - public ResponseEntity deleteGame( + public ResponseEntity deleteGame( HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.deleteGame(request, gameId); + return ResponseEntity.ok(gameService.deleteGame(request, gameId)); } //게임, 혜택 조회 @@ -131,11 +132,11 @@ public ResponseEntity deleteGame( @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @GetMapping("/{gameId}") - public ResponseEntity findGame( + public ResponseEntity findGame( HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.findGame(request, gameId); + return ResponseEntity.ok(gameService.findGame(request, gameId)); } //게임 조회 @@ -145,11 +146,11 @@ public ResponseEntity findGame( @ApiResponse(responseCode = "400", description = "조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) @GetMapping("/{gameId}/benefit") - public ResponseEntity findBenefit( + public ResponseEntity findBenefit( HttpServletRequest request, @PathVariable(value = "gameId") Long gameId ) throws JsonProcessingException { - return gameService.findBenefit(request, gameId); + return ResponseEntity.ok(gameService.findBenefit(request, gameId)); } } From 7d40f65ef0e2d16be282925433865e3bb1ff9ad2 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Tue, 12 Mar 2024 02:46:03 +0900 Subject: [PATCH 332/356] =?UTF-8?q?[Refactor]=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=98=B8=EC=B6=9C=EB=B0=A9=EB=B2=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GuestBookService.java | 40 +++------ .../presentation/GuestBookController.java | 17 ++-- .../image/application/ImageService.java | 82 ++++------------- .../image/presentation/ImageController.java | 37 ++++---- .../likes/application/LikesService.java | 18 +--- .../member/application/MemberService.java | 87 +++++-------------- .../member/presentation/MemberController.java | 34 ++++---- .../place/application/PlaceService.java | 47 +++------- .../place/presentation/PlaceController.java | 21 ++--- .../domain/road/application/RoadService.java | 36 ++------ .../road/presentation/RoadController.java | 17 ++-- .../domain/spot/application/SpotService.java | 31 ++----- .../spot/presentation/SpotController.java | 21 ++--- .../store/application/StoreService.java | 36 ++------ .../store/presentation/StoreController.java | 25 +++--- .../global/error/ApiControllerAdvice.java | 50 +++++------ 16 files changed, 201 insertions(+), 398 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index ec20a499..35e6fbe5 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -54,7 +54,7 @@ public class GuestBookService { // ResponseEntity 형식에 맞춰 빌드하는 메서드 @NonNull - private ResponseEntity getResponseEntity(GuestBook guestBook) { + private CommonDto getResponseEntity(GuestBook guestBook) { GuestBookResponseDto guestBookResponseDto; @@ -82,18 +82,13 @@ private ResponseEntity getResponseEntity(GuestBook guestBook) { throw new InvalidGuestBookException(); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(guestBookResponseDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, guestBookResponseDto); } // GuestBook(방명록) 을 하나 생성하는 Service Method 입니다. // Spot 이나 Store Controller 혹은 Service 단에서 불러와서 사용 가능합니다. @Transactional - public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuestBookRequestDto createGuestBookRequestDto) { + public CommonDto createGuestBook(HttpServletRequest request, CreateGuestBookRequestDto createGuestBookRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -163,11 +158,11 @@ public ResponseEntity createGuestBook(HttpServletRequest request, CreateGuest throw new InvalidGuestBookException(); } - return getResponseEntity(guestBook); + return new CommonDto(true, guestBook); } // Spot ID 로 GuestBook 을 조회하는 Method 입니다. - public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { + public CommonDto findGuestBookBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -188,17 +183,12 @@ public ResponseEntity findGuestBookBySpotId(HttpServletRequest request, Long .build() ).toList(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(guestBookResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, guestBookResponseDtoList); } // Store ID 로 GuestBook 을 조회하는 Method 입니다. - public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { + public CommonDto findGuestBookByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -219,18 +209,13 @@ public ResponseEntity findGuestBookByStoreId(HttpServletRequest request, Long .build() ).toList(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(guestBookResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, guestBookResponseDtoList); } // GuestBook 을 하나 Delete 하는 Method 입니다. @Transactional - public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestBookId) { + public CommonDto deleteGuestBook(HttpServletRequest request, Long guestBookId) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -245,11 +230,6 @@ public ResponseEntity deleteGuestBook(HttpServletRequest request, Long guestB //imageService.deleteImage(imageRepository.findByGuestBookId(guestBookId).orElseThrow(InvalidImageException::new).getId()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("방명록을 삭제했습니다").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("방명록을 삭제했습니다").build()); } } diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 24a8fdb0..cd8ce879 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -6,6 +6,7 @@ import com.ttubeog.domain.guestbook.dto.response.GuestBookResponseDto; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.CommonDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -60,11 +61,11 @@ public class GuestBookController { ) @PostMapping @ResponseStatus(value = HttpStatus.CREATED) - public ResponseEntity createGuestBook( + public ResponseEntity createGuestBook( @CurrentUser HttpServletRequest request, @RequestBody CreateGuestBookRequestDto createGuestBookRequestDto ) throws JsonProcessingException { - return guestBookService.createGuestBook(request, createGuestBookRequestDto); + return ResponseEntity.ok(guestBookService.createGuestBook(request, createGuestBookRequestDto)); } @@ -102,12 +103,12 @@ public ResponseEntity createGuestBook( ) @GetMapping("/{spotId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findGuestBookBySpotId( + public ResponseEntity findGuestBookBySpotId( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return guestBookService.findGuestBookBySpotId(request, spotId, pageNum); + return ResponseEntity.ok(guestBookService.findGuestBookBySpotId(request, spotId, pageNum)); } @@ -145,12 +146,12 @@ public ResponseEntity findGuestBookBySpotId( ) @GetMapping("/{storeId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findGuestBookByStoreId( + public ResponseEntity findGuestBookByStoreId( @CurrentUser HttpServletRequest request, @RequestParam(name = "storeId") Long storeId, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return guestBookService.findGuestBookByStoreId(request, storeId, pageNum); + return ResponseEntity.ok(guestBookService.findGuestBookByStoreId(request, storeId, pageNum)); } @@ -187,11 +188,11 @@ public ResponseEntity findGuestBookByStoreId( ) @DeleteMapping("/{guestBookId}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity deleteGuestBook( + public ResponseEntity deleteGuestBook( @CurrentUser HttpServletRequest request, @RequestParam(name = "guestBookId") Long guestBookId ) throws JsonProcessingException { - return guestBookService.deleteGuestBook(request, guestBookId); + return ResponseEntity.ok(guestBookService.deleteGuestBook(request, guestBookId)); } } diff --git a/src/main/java/com/ttubeog/domain/image/application/ImageService.java b/src/main/java/com/ttubeog/domain/image/application/ImageService.java index bd887566..ed0c6edc 100644 --- a/src/main/java/com/ttubeog/domain/image/application/ImageService.java +++ b/src/main/java/com/ttubeog/domain/image/application/ImageService.java @@ -45,7 +45,7 @@ public class ImageService { @Transactional - public ResponseEntity createSpotImage(HttpServletRequest request, Long spotId, List fileList) { + public CommonDto createSpotImage(HttpServletRequest request, Long spotId, List fileList) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -75,18 +75,12 @@ public ResponseEntity createSpotImage(HttpServletRequest request, Long spotId .build(); }).collect(Collectors.toList()); - - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } @Transactional - public ResponseEntity createStoreImage(HttpServletRequest request, Long storeId, List fileList) { + public CommonDto createStoreImage(HttpServletRequest request, Long storeId, List fileList) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -116,17 +110,12 @@ public ResponseEntity createStoreImage(HttpServletRequest request, Long store .build(); }).collect(Collectors.toList()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } @Transactional - public ResponseEntity createGuestBookImage(HttpServletRequest request, Long guestBookId, List fileList) { + public CommonDto createGuestBookImage(HttpServletRequest request, Long guestBookId, List fileList) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -156,16 +145,11 @@ public ResponseEntity createGuestBookImage(HttpServletRequest request, Long g .build(); }).collect(Collectors.toList()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } - public ResponseEntity findImageBySpotId(HttpServletRequest request, Long spotId) { + public CommonDto findImageBySpotId(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -185,16 +169,11 @@ public ResponseEntity findImageBySpotId(HttpServletRequest request, Long spot .build() ).toList(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } - public ResponseEntity findImageByStoreId(HttpServletRequest request, Long storeId) { + public CommonDto findImageByStoreId(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -214,16 +193,11 @@ public ResponseEntity findImageByStoreId(HttpServletRequest request, Long sto .build() ).toList(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } - public ResponseEntity findImageByGuestBookId(HttpServletRequest request, Long guestBookId) { + public CommonDto findImageByGuestBookId(HttpServletRequest request, Long guestBookId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -243,63 +217,43 @@ public ResponseEntity findImageByGuestBookId(HttpServletRequest request, Long .build() ).toList(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(imageResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, imageResponseDtoList); } @Transactional - public ResponseEntity deleteImageBySpotId(Long spotId) { + public CommonDto deleteImageBySpotId(Long spotId) { Spot spot = spotRepository.findById(spotId).orElseThrow(InvalidSpotIdException::new); List imageList = imageRepository.findAllBySpot(spot); imageRepository.deleteAll(imageList); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information("정상적으로 삭제되었습니다.") - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, "정상적으로 삭제되었습니다."); } @Transactional - public ResponseEntity deleteImageByStoreId(Long storeId) { + public CommonDto deleteImageByStoreId(Long storeId) { Store store = storeRepository.findById(storeId).orElseThrow(InvalidStoreIdException::new); List imageList = imageRepository.findAllByStore(store); imageRepository.deleteAll(imageList); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information("정상적으로 삭제되었습니다.") - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, "정상적으로 삭제되었습니다."); } @Transactional - public ResponseEntity deleteImageByGuestBookId(Long guestBookId) { + public CommonDto deleteImageByGuestBookId(Long guestBookId) { GuestBook guestBook = guestBookRepository.findById(guestBookId).orElseThrow(InvalidSpotIdException::new); List imageList = imageRepository.findAllByGuestBook(guestBook); imageRepository.deleteAll(imageList); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information("정상적으로 삭제되었습니다.") - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, "정상적으로 삭제되었습니다."); } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index 50774d38..c5a64d46 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.dto.response.ImageResponseDto; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -38,12 +39,12 @@ public class ImageController { }) // @ResponseStatus(value = HttpStatus.CREATED) @PostMapping(value = "/spot", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity createSpotImage( + public ResponseEntity createSpotImage( @CurrentUser HttpServletRequest request, @RequestParam Long spotId, @RequestPart List fileList ) { - return imageService.createSpotImage(request, spotId, fileList); + return ResponseEntity.ok(imageService.createSpotImage(request, spotId, fileList)); } @Operation(summary = "매장 이미지 저장", description = "매장의 이미지를 저장합니다.") @@ -53,12 +54,12 @@ public ResponseEntity createSpotImage( }) @PostMapping(value = "/store", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) // @ResponseStatus(value = HttpStatus.CREATED) - public ResponseEntity createStoreImage( + public ResponseEntity createStoreImage( @CurrentUser HttpServletRequest request, @RequestParam Long storeId, @RequestPart List fileList ) { - return imageService.createStoreImage(request, storeId, fileList); + return ResponseEntity.ok(imageService.createStoreImage(request, storeId, fileList)); } @Operation(summary = "방명록 이미지 저장", description = "방명록의 이미지를 저장합니다.") @@ -68,12 +69,12 @@ public ResponseEntity createStoreImage( }) @PostMapping(value = "/guestbook", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) // @ResponseStatus(value = HttpStatus.CREATED) - public ResponseEntity createGuestBookImage( + public ResponseEntity createGuestBookImage( @CurrentUser HttpServletRequest request, @RequestParam Long guestBookId, @RequestPart List fileList ) { - return imageService.createGuestBookImage(request, guestBookId, fileList); + return ResponseEntity.ok(imageService.createGuestBookImage(request, guestBookId, fileList)); } @Operation(summary = "산책스팟 이미지 조회", description = "산책스팟ID로 해당 이미지를 조회합니다.") @@ -83,11 +84,11 @@ public ResponseEntity createGuestBookImage( }) @GetMapping(value = "/{spotId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findImageBySpotId( + public ResponseEntity findImageBySpotId( @CurrentUser HttpServletRequest request, @RequestParam Long spotId ) { - return imageService.findImageBySpotId(request, spotId); + return ResponseEntity.ok(imageService.findImageBySpotId(request, spotId)); } @Operation(summary = "매장 이미지 조회", description = "매장ID로 해당 이미지를 조회합니다.") @@ -97,11 +98,11 @@ public ResponseEntity findImageBySpotId( }) @GetMapping(value = "/{storeId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findImageByStoreId( + public ResponseEntity findImageByStoreId( @CurrentUser HttpServletRequest request, @RequestParam Long storeId ) { - return imageService.findImageByStoreId(request, storeId); + return ResponseEntity.ok(imageService.findImageByStoreId(request, storeId)); } @Operation(summary = "방명록 이미지 조회", description = "방명록ID로 해당 이미지를 조회합니다.") @@ -111,11 +112,11 @@ public ResponseEntity findImageByStoreId( }) @GetMapping(value = "/{guestBookId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findImageByGuestBookId( + public ResponseEntity findImageByGuestBookId( @CurrentUser HttpServletRequest request, @RequestParam Long guestBookId ) { - return imageService.findImageByGuestBookId(request, guestBookId); + return ResponseEntity.ok(imageService.findImageByGuestBookId(request, guestBookId)); } @@ -126,10 +127,10 @@ public ResponseEntity findImageByGuestBookId( }) @DeleteMapping(value = "/{spotId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity deleteImageBySpotId( + public ResponseEntity deleteImageBySpotId( @RequestParam Long spotId ) { - return imageService.deleteImageBySpotId(spotId); + return ResponseEntity.ok(imageService.deleteImageBySpotId(spotId)); } @Operation(summary = "매장 이미지 삭제", description = "매장의 이미지를 삭제합니다.") @@ -139,10 +140,10 @@ public ResponseEntity deleteImageBySpotId( }) @DeleteMapping(value = "/{storeId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity deleteImageByStoreId( + public ResponseEntity deleteImageByStoreId( @RequestParam Long storeId ) { - return imageService.deleteImageByStoreId(storeId); + return ResponseEntity.ok(imageService.deleteImageByStoreId(storeId)); } @Operation(summary = "방명록 이미지 삭제", description = "방명록의 이미지를 삭제합니다.") @@ -152,9 +153,9 @@ public ResponseEntity deleteImageByStoreId( }) @DeleteMapping(value = "/{guestBookId}") // @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity deleteImageByGuestBookId( + public ResponseEntity deleteImageByGuestBookId( @RequestParam Long guestBookId ) { - return imageService.deleteImageByGuestBookId(guestBookId); + return ResponseEntity.ok(imageService.deleteImageByGuestBookId(guestBookId)); } } diff --git a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java index a79527b0..f3993bfe 100644 --- a/src/main/java/com/ttubeog/domain/likes/application/LikesService.java +++ b/src/main/java/com/ttubeog/domain/likes/application/LikesService.java @@ -35,7 +35,7 @@ public class LikesService { // 매장 좋아요 누르기 @Transactional - public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { + public CommonDto likesStore(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -52,17 +52,12 @@ public ResponseEntity likesStore(HttpServletRequest request, Long storeId) { likesRepository.save(likes); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("매장에 대한 좋아요를 눌렀습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("매장에 대한 좋아요를 눌렀습니다.").build()); } // 산책스팟 좋아요 누르기 @Transactional - public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { + public CommonDto likesSpot(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -79,11 +74,6 @@ public ResponseEntity likesSpot(HttpServletRequest request, Long spotId) { likesRepository.save(likes); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("스팟에 대한 좋아요를 눌렀습니다.").build()); } } \ No newline at end of file diff --git a/src/main/java/com/ttubeog/domain/member/application/MemberService.java b/src/main/java/com/ttubeog/domain/member/application/MemberService.java index 498e0658..c32023a8 100644 --- a/src/main/java/com/ttubeog/domain/member/application/MemberService.java +++ b/src/main/java/com/ttubeog/domain/member/application/MemberService.java @@ -47,10 +47,8 @@ public class MemberService { private final SpotRepository spotRepository; private static final int WAITING_PERIOD_DAYS = 3; - - // 현재 유저 조회 - public ResponseEntity getCurrentUser(HttpServletRequest request) { + public CommonDto getCurrentUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); Optional checkMember = memberRepository.findById(memberId); @@ -63,16 +61,11 @@ public ResponseEntity getCurrentUser(HttpServletRequest request) { .platform(member.getPlatform()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(memberDetailDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, memberDetailDto); } @Transactional - public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { + public CommonDto postMemberNickname(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); // 닉네임 1회 변경 여부 확인 @@ -88,12 +81,7 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN .nicknameChanged(checkMember.getNicknameChange()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(false) - .information(memberNicknameDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(false, memberNicknameDto); } } @@ -113,31 +101,22 @@ public ResponseEntity postMemberNickname(HttpServletRequest request, ProduceN .nicknameChanged(member.getNicknameChange()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(memberNicknameDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, memberNicknameDto); } @Transactional // 닉네임 중복 확인 - public ResponseEntity postMemberNicknameCheck(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { + public CommonDto postMemberNicknameCheck(HttpServletRequest request, ProduceNicknameRequest produceNicknameRequest) { Long memberId = jwtTokenProvider.getMemberId(request); Boolean isNicknameUsed = memberRepository.existsByNickname(produceNicknameRequest.getNickname()); - CommonDto apiResponse = CommonDto.builder() - .check(!isNicknameUsed) - .information("닉네임 중복이면 check -> false, 중복이 아니면 check -> true") - .build(); - return ResponseEntity.ok(apiResponse); + return new CommonDto(!isNicknameUsed, "닉네임 중복이면 check -> false, 중복이 아니면 check -> true"); } @Transactional // 토큰 재발급 설정 - public ResponseEntity getMemberReissueToken(HttpServletRequest request) { + public CommonDto getMemberReissueToken(HttpServletRequest request) { Long memberId; try { @@ -162,28 +141,19 @@ public ResponseEntity getMemberReissueToken(HttpServletRequest request) { OAuthTokenResponse oAuthTokenResponse = new OAuthTokenResponse(newAccessToken, newRefreshToken, member.isRegisteredOAuthMember()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(oAuthTokenResponse) - .build(); - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, oAuthTokenResponse); } catch (Exception e) { - return ResponseEntity.badRequest().body(new InvalidAccessTokenExpiredException()); + throw new InvalidAccessTokenExpiredException(); } } @Transactional // 로그아웃 - public ResponseEntity deleteLogout(HttpServletRequest request) { + public CommonDto deleteLogout(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); deleteValueByKey(String.valueOf(memberId)); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("성공적으로 로그아웃 되었습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("성공적으로 로그아웃 되었습니다.").build()); } public void deleteValueByKey(String key) { @@ -191,7 +161,7 @@ public void deleteValueByKey(String key) { } @Transactional - public ResponseEntity deleteUser(HttpServletRequest request) { + public CommonDto deleteUser(HttpServletRequest request) { Long memberId = jwtTokenProvider.getMemberId(request); Optional checkMember = memberRepository.findById(memberId); @@ -215,18 +185,11 @@ public ResponseEntity deleteUser(HttpServletRequest request) { memberRepository.save(member); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("성공적으로 회원탈퇴 되었습니다.").build()); } - - @Transactional - public ResponseEntity deleteInactiveMember() { + public CommonDto deleteInactiveMember() { try { // 비활성화 된 회원 찾기 List memberStatus = memberRepository.findByStatus(Status.INACTIVE); @@ -236,14 +199,14 @@ public ResponseEntity deleteInactiveMember() { memberRepository.delete(member); } - return ResponseEntity.ok("비활성화된 회원 탈퇴 완료"); + return new CommonDto(true, "비활성화된 회원 탈퇴 완료"); } catch (Exception e) { throw new FailureMemberDeleteException(); } } @Transactional - public ResponseEntity getMySpotList(HttpServletRequest request, Integer pageNum) { + public CommonDto getMySpotList(HttpServletRequest request, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); Page spotPage = spotRepository.findAllByMemberId(memberId, PageRequest.of(pageNum, 10)); @@ -259,16 +222,11 @@ public ResponseEntity getMySpotList(HttpServletRequest request, Integer pageN memberPlaceDtoList.add(memberPlaceDto); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(memberPlaceDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, memberPlaceDtoList); } @Transactional - public ResponseEntity getMyStoreList(HttpServletRequest request, Integer pageNum) { + public CommonDto getMyStoreList(HttpServletRequest request, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); List spotsByMemberId = memberRepository.findStoreByMemberId(memberId); @@ -286,11 +244,6 @@ public ResponseEntity getMyStoreList(HttpServletRequest request, Integer page memberPlaceDtoList.add(memberPlaceDto); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(memberPlaceDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, memberPlaceDtoList); } } diff --git a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java index b3eb58a5..a8625f33 100644 --- a/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java +++ b/src/main/java/com/ttubeog/domain/member/presentation/MemberController.java @@ -41,11 +41,11 @@ public class MemberController { @ApiResponse(responseCode = "400", description = "멤버 확인 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("") - public ResponseEntity getCurrentMember( + public ResponseEntity getCurrentMember( HttpServletRequest request ) { - return memberService.getCurrentUser(request); + return ResponseEntity.ok(memberService.getCurrentUser(request)); } @Operation(summary = "닉네임 설정", description = "현재 접속된 멤버의 초기 닉네임을 설정합니다.닉네임을 이미 변경한 유저는 isChanged == true로 반환되며, 닉네임이 업데이트 되지 않습니다.") @@ -54,10 +54,10 @@ public ResponseEntity getCurrentMember( @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname") - public ResponseEntity postMemberNickname( + public ResponseEntity postMemberNickname( HttpServletRequest request, @RequestBody ProduceNicknameRequest produceNicknameRequest ) { - return memberService.postMemberNickname(request, produceNicknameRequest); + return ResponseEntity.ok(memberService.postMemberNickname(request, produceNicknameRequest)); } @Operation(summary = "닉네임 중복 확인", description = "닉네임의 중복을 확인합니다.") @@ -66,10 +66,10 @@ public ResponseEntity postMemberNickname( @ApiResponse(responseCode = "400", description = "닉네임 설정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @PostMapping(value = "/nickname/check") - public ResponseEntity checkNicknameAvailability( + public ResponseEntity checkNicknameAvailability( HttpServletRequest request, @RequestBody ProduceNicknameRequest produceNicknameRequest ) { - return memberService.postMemberNicknameCheck(request, produceNicknameRequest); + return ResponseEntity.ok(memberService.postMemberNicknameCheck(request, produceNicknameRequest)); } @@ -79,11 +79,11 @@ public ResponseEntity checkNicknameAvailability( @ApiResponse(responseCode = "400", description = "토큰 재발급 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @GetMapping("/login/reissue") - public ResponseEntity loginReissue( + public ResponseEntity loginReissue( HttpServletRequest request ) { - return memberService.getMemberReissueToken(request); + return ResponseEntity.ok(memberService.getMemberReissueToken(request)); } @Operation(summary = "로그아웃", description = "현재 접속된 멤버가 로그아웃 합니다.") @@ -92,10 +92,10 @@ public ResponseEntity loginReissue( @ApiResponse(responseCode = "400", description = "로그아웃 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) @DeleteMapping("/logout") - public ResponseEntity logout( + public ResponseEntity logout( HttpServletRequest request ) { - return memberService.deleteLogout(request); + return ResponseEntity.ok(memberService.deleteLogout(request)); } // @Operation(summary = "회원탈퇴", description = "현재 접속된 회원이 탈퇴 합니다.") @@ -104,16 +104,16 @@ public ResponseEntity logout( // @ApiResponse(responseCode = "400", description = "회원탈퇴 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), // }) // @DeleteMapping("/delete") -// public ResponseEntity deleteUser( +// public ResponseEntity deleteUser( // HttpServletRequest request // ) { -// ResponseEntity responseEntity = memberService.deleteUser(request); +// ResponseEntity responseEntity = memberService.deleteUser(request); // // if (responseEntity.getStatusCode().is2xxSuccessful()) { // LocalDateTime localDateTime = LocalDateTime.now().plusDays(3); // // scheduledExecutorService.schedule(() -> { -// ResponseEntity deleteResponse = memberService.deleteInactiveMember(); +// ResponseEntity deleteResponse = memberService.deleteInactiveMember(); // // if (deleteResponse.getStatusCode().is2xxSuccessful()) { // System.out.println("회원 삭제 성공"); @@ -159,11 +159,11 @@ public ResponseEntity logout( } ) @GetMapping("/spot&{pageNum}") - public ResponseEntity getMySpotList( + public ResponseEntity getMySpotList( @CurrentUser HttpServletRequest request, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return memberService.getMySpotList(request, pageNum); + return ResponseEntity.ok(memberService.getMySpotList(request, pageNum)); } /** @@ -200,10 +200,10 @@ public ResponseEntity getMySpotList( } ) @GetMapping("/store&{pageNum}") - public ResponseEntity getMyStoreList( + public ResponseEntity getMyStoreList( @CurrentUser HttpServletRequest request, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return memberService.getMyStoreList(request, pageNum); + return ResponseEntity.ok(memberService.getMyStoreList(request, pageNum)); } } diff --git a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java index de9bfe41..6a2fad4d 100644 --- a/src/main/java/com/ttubeog/domain/place/application/PlaceService.java +++ b/src/main/java/com/ttubeog/domain/place/application/PlaceService.java @@ -164,19 +164,14 @@ private GetAllPlaceRes mapSpotToDto(HttpServletRequest request, Spot spot) { // 전체 조회 @Transactional - public ResponseEntity getAllPlaces(HttpServletRequest request, Pageable pageable) { + public CommonDto getAllPlaces(HttpServletRequest request, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); List allPlaces = getAllPlaceResList(request, pageable); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(allPlaces) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, allPlaces); } public int calculateRecommendationScore(float stars, int guestbookCount, int likesCount) { @@ -213,7 +208,7 @@ private int calculateLikesStore(int likesCount) { // 추천순 조회 @Transactional - public ResponseEntity getAllPlacesRecommended(HttpServletRequest request, Pageable pageable) { + public CommonDto getAllPlacesRecommended(HttpServletRequest request, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -226,12 +221,7 @@ public ResponseEntity getAllPlacesRecommended(HttpServletRequest request, Pag allPlaces.sort(Comparator.comparingInt(GetAllPlaceRes::getRecommendationScore).reversed()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(allPlaces) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, allPlaces); } private double calculateDistance(Double lat1, Double lon1, Double lat2, Double lon2) { @@ -252,7 +242,7 @@ private double calculateDistance(Double lat1, Double lon1, Double lat2, Double l // 거리순 조회 @Transactional - public ResponseEntity getAllPlacesNearby(HttpServletRequest request, GetNearbyPlaceReq getNearbyPlaceReq, Pageable pageable) { + public CommonDto getAllPlacesNearby(HttpServletRequest request, GetNearbyPlaceReq getNearbyPlaceReq, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -268,34 +258,24 @@ public ResponseEntity getAllPlacesNearby(HttpServletRequest request, GetNearb allPlaces.sort(Comparator.comparingDouble(GetAllPlaceRes::getDistance)); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(allPlaces) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, allPlaces); } // 최신순 조회 @Transactional - public ResponseEntity getAllPlacesLatest(HttpServletRequest request, Pageable pageable) { + public CommonDto getAllPlacesLatest(HttpServletRequest request, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); List allPlaces = getAllPlaceResList(request, pageable); allPlaces.sort(Comparator.comparing(GetAllPlaceRes::getCreatedAt).reversed()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(allPlaces) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, allPlaces); } // 장소 검색 @Transactional - public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq searchPlaceReq, Pageable pageable) { + public CommonDto searchPlaces(HttpServletRequest request, SearchPlaceReq searchPlaceReq, Pageable pageable) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -329,7 +309,7 @@ public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq // 반환할 데이터가 없으면 빈 목록 반환 if (paginatedResult.isEmpty()) { - return ResponseEntity.ok().body(Collections.emptyList()); + return new CommonDto(true, Collections.emptyList()); } List searchPlaceRes = paginatedResult.stream() @@ -350,11 +330,6 @@ public ResponseEntity searchPlaces(HttpServletRequest request, SearchPlaceReq .build()) .collect(Collectors.toList()); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(searchPlaceRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, searchPlaceRes); } } diff --git a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java index b4f4dc4c..5bf7962f 100644 --- a/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/ttubeog/domain/place/presentation/PlaceController.java @@ -5,6 +5,7 @@ import com.ttubeog.domain.place.dto.request.SearchPlaceReq; import com.ttubeog.domain.place.dto.response.GetAllPlaceRes; import com.ttubeog.domain.place.dto.response.SearchPlaceRes; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -35,13 +36,13 @@ public class PlaceController { @ApiResponse(responseCode = "400", description = "전체 장소 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping - public ResponseEntity getAllPlaces( + public ResponseEntity getAllPlaces( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlaces(request, pageable); + return ResponseEntity.ok(placeService.getAllPlaces(request, pageable)); } // 추천순 조회 @@ -51,13 +52,13 @@ public ResponseEntity getAllPlaces( @ApiResponse(responseCode = "400", description = "추천순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/recommended") - public ResponseEntity getAllPlacesRecommended( + public ResponseEntity getAllPlacesRecommended( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesRecommended(request, pageable); + return ResponseEntity.ok(placeService.getAllPlacesRecommended(request, pageable)); } // 거리순 조회 @@ -67,14 +68,14 @@ public ResponseEntity getAllPlacesRecommended( @ApiResponse(responseCode = "400", description = "거리순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/nearby") - public ResponseEntity getAllPlacesNearby( + public ResponseEntity getAllPlacesNearby( HttpServletRequest request, @Valid GetNearbyPlaceReq getNearbyPlaceReq, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesNearby(request, getNearbyPlaceReq, pageable); + return ResponseEntity.ok(placeService.getAllPlacesNearby(request, getNearbyPlaceReq, pageable)); } // 최신순 조회 @@ -84,13 +85,13 @@ public ResponseEntity getAllPlacesNearby( @ApiResponse(responseCode = "400", description = "최신순 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/latest") - public ResponseEntity getAllPlacesLatest( + public ResponseEntity getAllPlacesLatest( HttpServletRequest request, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.getAllPlacesLatest(request, pageable); + return ResponseEntity.ok(placeService.getAllPlacesLatest(request, pageable)); } // 장소 검색 @@ -100,13 +101,13 @@ public ResponseEntity getAllPlacesLatest( @ApiResponse(responseCode = "400", description = "장소 검색 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/search") - public ResponseEntity searchPlace( + public ResponseEntity searchPlace( HttpServletRequest request, @Valid SearchPlaceReq searchPlaceReq, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { Pageable pageable = PageRequest.of(page, size); - return placeService.searchPlaces(request, searchPlaceReq, pageable); + return ResponseEntity.ok(placeService.searchPlaces(request, searchPlaceReq, pageable)); } } diff --git a/src/main/java/com/ttubeog/domain/road/application/RoadService.java b/src/main/java/com/ttubeog/domain/road/application/RoadService.java index 14af8230..e48012f6 100644 --- a/src/main/java/com/ttubeog/domain/road/application/RoadService.java +++ b/src/main/java/com/ttubeog/domain/road/application/RoadService.java @@ -47,7 +47,7 @@ public class RoadService { private final JwtTokenProvider jwtTokenProvider; @Transactional - public ResponseEntity createRoad(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { + public CommonDto createRoad(HttpServletRequest request, CreateRoadRequestDto createRoadRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -144,15 +144,10 @@ public ResponseEntity createRoad(HttpServletRequest request, CreateRoadReques throw new InvalidRoadTypeException(); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(roadResponseDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, roadResponseDto); } - public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { + public CommonDto findRoadBySpotId(HttpServletRequest request, Long spotId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -183,15 +178,10 @@ public ResponseEntity findRoadBySpotId(HttpServletRequest request, Long spotI roadResponseDtoList.add(roadResponseDto); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(roadResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, roadResponseDtoList); } - public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { + public CommonDto findRoadByStoreId(HttpServletRequest request, Long storeId, Integer pageNum) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -222,16 +212,11 @@ public ResponseEntity findRoadByStoreId(HttpServletRequest request, Long stor roadResponseDtoList.add(roadResponseDto); } - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(roadResponseDtoList) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, roadResponseDtoList); } @Transactional - public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { + public CommonDto deleteRoad(HttpServletRequest request, Long roadId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -249,11 +234,6 @@ public ResponseEntity deleteRoad(HttpServletRequest request, Long roadId) { roadCoordinateRepository.deleteAll(roadCoordinateList); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("산책로를 삭제했습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("산책로를 삭제했습니다.").build()); } } diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index d913cd7a..e262a3cf 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -7,6 +7,7 @@ import com.ttubeog.domain.road.dto.request.CreateRoadRequestDto; import com.ttubeog.domain.road.dto.response.RoadResponseDto; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.CommonDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -60,11 +61,11 @@ public class RoadController { ) @PostMapping @ResponseStatus(value = HttpStatus.CREATED) - public ResponseEntity createRoad( + public ResponseEntity createRoad( @CurrentUser HttpServletRequest request, @RequestBody CreateRoadRequestDto createRoadRequestDto ) throws JsonProcessingException { - return roadService.createRoad(request, createRoadRequestDto); + return ResponseEntity.ok(roadService.createRoad(request, createRoadRequestDto)); } /** @@ -101,12 +102,12 @@ public ResponseEntity createRoad( ) @GetMapping("/{spotId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findRoadBySpotId( + public ResponseEntity findRoadBySpotId( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return roadService.findRoadBySpotId(request, spotId, pageNum); + return ResponseEntity.ok(roadService.findRoadBySpotId(request, spotId, pageNum)); } @@ -144,12 +145,12 @@ public ResponseEntity findRoadBySpotId( ) @GetMapping("/{storeId}&{pageNum}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity findRoadByStoreId( + public ResponseEntity findRoadByStoreId( @CurrentUser HttpServletRequest request, @RequestParam(name = "storeId") Long storeId, @RequestParam(name = "pageNum") Integer pageNum ) throws JsonProcessingException { - return roadService.findRoadByStoreId(request, storeId, pageNum); + return ResponseEntity.ok(roadService.findRoadByStoreId(request, storeId, pageNum)); } @@ -186,10 +187,10 @@ public ResponseEntity findRoadByStoreId( ) @DeleteMapping("/{roadId}") @ResponseStatus(value = HttpStatus.OK) - public ResponseEntity deleteRoad( + public ResponseEntity deleteRoad( @CurrentUser HttpServletRequest request, @RequestParam(name = "roadId") Long roadId ) throws JsonProcessingException { - return roadService.deleteRoad(request, roadId); + return ResponseEntity.ok(roadService.deleteRoad(request, roadId)); } } diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 9d9c371b..5444a5bc 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -51,7 +51,7 @@ public class SpotService { private final JwtTokenProvider jwtTokenProvider; @NonNull - private ResponseEntity getResponseEntity(Spot spot) { + private CommonDto getResponseEntity(Spot spot) { SpotResponseDto createSpotResponseDto = SpotResponseDto.builder() .id(spot.getId()) @@ -65,17 +65,12 @@ private ResponseEntity getResponseEntity(Spot spot) { .stars(spot.getStars()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(createSpotResponseDto) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, createSpotResponseDto); } //Spot 생성 Method @Transactional - public ResponseEntity createSpot(HttpServletRequest request, CreateSpotRequestDto createSpotRequestDto) { + public CommonDto createSpot(HttpServletRequest request, CreateSpotRequestDto createSpotRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -110,7 +105,7 @@ public ResponseEntity createSpot(HttpServletRequest request, CreateSpotReques } //ID로 스팟 조회 Method - public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { + public CommonDto findBySpotId(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -135,16 +130,11 @@ public ResponseEntity findBySpotId(HttpServletRequest request, Long spotId) { .isFavorited(isFavorited) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(getSpotDetailRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, getSpotDetailRes); } @Transactional - public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, UpdateSpotRequestDto updateSpotRequestDto) { + public CommonDto updateSpot(HttpServletRequest request, Long spotId, UpdateSpotRequestDto updateSpotRequestDto) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -180,7 +170,7 @@ public ResponseEntity updateSpot(HttpServletRequest request, Long spotId, Upd //Spot 삭제 Method @Transactional - public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { + public CommonDto deleteSpot(HttpServletRequest request, Long spotId) { Long memberId = jwtTokenProvider.getMemberId(request); @@ -201,11 +191,6 @@ public ResponseEntity deleteSpot(HttpServletRequest request, Long spotId) { List guestBookList = guestBookRepository.findAllBySpot(spot); guestBookRepository.deleteAll(guestBookList); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("산책 스팟을 삭제햇습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("산책 스팟을 삭제햇습니다.").build()); } } diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 8672a57f..86e94f8d 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -13,6 +13,7 @@ import com.ttubeog.domain.spot.exception.InvalidDongAreaException; import com.ttubeog.domain.spot.exception.InvalidImageListSizeException; import com.ttubeog.global.config.security.token.CurrentUser; +import com.ttubeog.global.payload.CommonDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -99,11 +100,11 @@ public class SpotController { ) @PostMapping @ResponseStatus(value = HttpStatus.CREATED) - public ResponseEntity createSpot( + public ResponseEntity createSpot( @CurrentUser HttpServletRequest request, @RequestBody CreateSpotRequestDto createSpotRequestDto ) throws JsonProcessingException { - return spotService.createSpot(request, createSpotRequestDto); + return ResponseEntity.ok(spotService.createSpot(request, createSpotRequestDto)); } @@ -169,11 +170,11 @@ public ResponseEntity createSpot( } ) @GetMapping("/{spotId}") - public ResponseEntity findBySpotId( + public ResponseEntity findBySpotId( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return spotService.findBySpotId(request, spotId); + return ResponseEntity.ok(spotService.findBySpotId(request, spotId)); } @@ -242,12 +243,12 @@ public ResponseEntity findBySpotId( } ) @PatchMapping - public ResponseEntity updateSpot( + public ResponseEntity updateSpot( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId, @RequestBody UpdateSpotRequestDto updateSpotRequestDto ) throws JsonProcessingException { - return spotService.updateSpot(request, spotId, updateSpotRequestDto); + return ResponseEntity.ok(spotService.updateSpot(request, spotId, updateSpotRequestDto)); } /** @@ -313,11 +314,11 @@ public ResponseEntity updateSpot( } ) @DeleteMapping("/{spotId}") - public ResponseEntity deleteSpot( + public ResponseEntity deleteSpot( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return spotService.deleteSpot(request, spotId); + return ResponseEntity.ok(spotService.deleteSpot(request, spotId)); } @@ -384,10 +385,10 @@ public ResponseEntity deleteSpot( } ) @PatchMapping("/{spotId}/likes") - public ResponseEntity likeSpot( + public ResponseEntity likeSpot( @CurrentUser HttpServletRequest request, @RequestParam(name = "spotId") Long spotId ) throws JsonProcessingException { - return likesService.likesSpot(request, spotId); + return ResponseEntity.ok(likesService.likesSpot(request, spotId)); } } diff --git a/src/main/java/com/ttubeog/domain/store/application/StoreService.java b/src/main/java/com/ttubeog/domain/store/application/StoreService.java index 947744af..6700b621 100644 --- a/src/main/java/com/ttubeog/domain/store/application/StoreService.java +++ b/src/main/java/com/ttubeog/domain/store/application/StoreService.java @@ -60,7 +60,7 @@ public class StoreService { // 매장 등록 @Transactional - public ResponseEntity registerStore(HttpServletRequest request, RegisterStoreReq registerStoreReq) { + public CommonDto registerStore(HttpServletRequest request, RegisterStoreReq registerStoreReq) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -98,17 +98,12 @@ public ResponseEntity registerStore(HttpServletRequest request, RegisterStore .type(store.getType()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(registerStoreRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, registerStoreRes); } // 매장 수정 @Transactional - public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq updateStoreReq) { + public CommonDto updateStore(HttpServletRequest request, UpdateStoreReq updateStoreReq) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -145,17 +140,12 @@ public ResponseEntity updateStore(HttpServletRequest request, UpdateStoreReq .type(store.getType()) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(updateStoreRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, updateStoreRes); } // 매장 삭제 @Transactional - public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { + public CommonDto deleteStore(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -203,16 +193,11 @@ public ResponseEntity deleteStore(HttpServletRequest request, Long storeId) { storeRepository.delete(store); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, Message.builder().message("매장 정보가 정상적으로 삭제되었습니다.").build()); } // 매장 세부사항 조회 - public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeId) { + public CommonDto getStoreDetails(HttpServletRequest request, Long storeId) { Long memberId = jwtTokenProvider.getMemberId(request); Member member = memberRepository.findById(memberId).orElseThrow(InvalidMemberException::new); @@ -243,11 +228,6 @@ public ResponseEntity getStoreDetails(HttpServletRequest request, Long storeI .isFavorited(isFavorited) .build(); - CommonDto apiResponse = CommonDto.builder() - .check(true) - .information(getStoreDetailRes) - .build(); - - return ResponseEntity.ok(apiResponse); + return new CommonDto(true, getStoreDetailRes); } } diff --git a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java index 50837858..8f0997c7 100644 --- a/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java +++ b/src/main/java/com/ttubeog/domain/store/presentation/StoreController.java @@ -11,6 +11,7 @@ import com.ttubeog.domain.store.dto.response.GetStoreDetailRes; import com.ttubeog.domain.store.dto.response.RegisterStoreRes; import com.ttubeog.domain.store.dto.response.UpdateStoreRes; +import com.ttubeog.global.payload.CommonDto; import com.ttubeog.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -43,11 +44,11 @@ public class StoreController { @ApiResponse(responseCode = "400", description = "매장 등록 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping - public ResponseEntity registerStore( + public ResponseEntity registerStore( HttpServletRequest request, @Valid @RequestBody RegisterStoreReq registerStoreReq ) { - return storeService.registerStore(request, registerStoreReq); + return ResponseEntity.ok(storeService.registerStore(request, registerStoreReq)); } // 매장 수정 @@ -57,11 +58,11 @@ public ResponseEntity registerStore( @ApiResponse(responseCode = "400", description = "매장 수정 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PatchMapping - public ResponseEntity updateStore( + public ResponseEntity updateStore( HttpServletRequest request, @Valid @RequestBody UpdateStoreReq updateStoreReq ) { - return storeService.updateStore(request, updateStoreReq); + return ResponseEntity.ok(storeService.updateStore(request, updateStoreReq)); } // 매장 삭제 @@ -71,11 +72,11 @@ public ResponseEntity updateStore( @ApiResponse(responseCode = "400", description = "매장 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @DeleteMapping("/{storeId}") - public ResponseEntity deleteStore( + public ResponseEntity deleteStore( HttpServletRequest request, @PathVariable Long storeId ) { - return storeService.deleteStore(request, storeId); + return ResponseEntity.ok(storeService.deleteStore(request, storeId)); } // 매장 세부사항 조회 @@ -85,11 +86,11 @@ public ResponseEntity deleteStore( @ApiResponse(responseCode = "400", description = "매장 세부사항 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/{storeId}") - public ResponseEntity getStoreDetails( + public ResponseEntity getStoreDetails( HttpServletRequest request, @PathVariable Long storeId ) { - return storeService.getStoreDetails(request, storeId); + return ResponseEntity.ok(storeService.getStoreDetails(request, storeId)); } // 매장 좋아요 누르기 @@ -99,11 +100,11 @@ public ResponseEntity getStoreDetails( @ApiResponse(responseCode = "400", description = "매장 좋아요 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @PostMapping("/{storeId}/likes") - public ResponseEntity likesStore( + public ResponseEntity likesStore( HttpServletRequest request, @PathVariable Long storeId ) { - return likesService.likesStore(request, storeId); + return ResponseEntity.ok(likesService.likesStore(request, storeId)); } //StoreId로 매장, 혜택 조회 @@ -113,10 +114,10 @@ public ResponseEntity likesStore( @ApiResponse(responseCode = "400", description = "게임 조회 누르기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) }) @GetMapping("/{storeId}/game") - public ResponseEntity findBenefitByStore( + public ResponseEntity findBenefitByStore( HttpServletRequest request, @PathVariable Long storeId ) throws JsonProcessingException { - return gameService.findByStore(request, storeId); + return ResponseEntity.ok(gameService.findByStore(request, storeId)); } } diff --git a/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java b/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java index 75933f15..4cc18d9c 100644 --- a/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java +++ b/src/main/java/com/ttubeog/global/error/ApiControllerAdvice.java @@ -16,7 +16,7 @@ public class ApiControllerAdvice { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - protected ResponseEntity handleHttpRequestMethodNotSupportedException( + protected ResponseEntity handleHttpRequestMethodNotSupportedException( HttpRequestMethodNotSupportedException e) { final ErrorResponse response = ErrorResponse @@ -26,12 +26,12 @@ protected ResponseEntity handleHttpRequestMethodNotSupportedException( .clazz(e.getMethod()) .message(e.getMessage()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.METHOD_NOT_ALLOWED); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.METHOD_NOT_ALLOWED); } @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { ErrorResponse response = ErrorResponse .builder() @@ -42,12 +42,12 @@ public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNot .fieldErrors(e.getFieldErrors()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.OK); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.OK); } @ExceptionHandler(InvalidParameterException.class) - public ResponseEntity handleInvalidParameterException(InvalidParameterException e) { + public ResponseEntity handleInvalidParameterException(InvalidParameterException e) { ErrorResponse response = ErrorResponse .builder() .status(HttpStatus.METHOD_NOT_ALLOWED.value()) @@ -56,13 +56,13 @@ public ResponseEntity handleInvalidParameterException(InvalidParameterExcepti .message(e.toString()) .fieldErrors(e.getFieldErrors()) .build(); - - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.OK); + + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.OK); } @ExceptionHandler(DefaultException.class) - protected ResponseEntity handleDefaultException(DefaultException e) { + protected ResponseEntity handleDefaultException(DefaultException e) { ErrorCode errorCode = e.getErrorCode(); @@ -73,56 +73,56 @@ protected ResponseEntity handleDefaultException(DefaultException e) { .message(e.toString()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.resolve(errorCode.getStatus())); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.resolve(errorCode.getStatus())); } @ExceptionHandler(Exception.class) - protected ResponseEntity handleException(Exception e) { + protected ResponseEntity handleException(Exception e) { ErrorResponse response = ErrorResponse .builder() .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message(e.toString()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(AuthenticationException.class) - protected ResponseEntity handleAuthenticationException(AuthenticationException e) { + protected ResponseEntity handleAuthenticationException(AuthenticationException e) { ErrorResponse response = ErrorResponse .builder() .status(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED.value()) .message(e.getMessage()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(DefaultAuthenticationException.class) - protected ResponseEntity handleCustomAuthenticationException(DefaultAuthenticationException e) { + protected ResponseEntity handleCustomAuthenticationException(DefaultAuthenticationException e) { ErrorResponse response = ErrorResponse .builder() .status(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED.value()) .message(e.getMessage()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(DefaultNullPointerException.class) - protected ResponseEntity handleNullPointerException(DefaultNullPointerException e) { + protected ResponseEntity handleNullPointerException(DefaultNullPointerException e) { ErrorResponse response = ErrorResponse .builder() .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message(e.getMessage()) .build(); - CommonDto apiResponse = CommonDto.builder().check(false).information(response).build(); - return new ResponseEntity<>(apiResponse, HttpStatus.INTERNAL_SERVER_ERROR); + CommonDto commonDto = CommonDto.builder().check(false).information(response).build(); + return new ResponseEntity<>(commonDto, HttpStatus.INTERNAL_SERVER_ERROR); } } \ No newline at end of file From 0258f8bfea4113b04c464eee7c6d2b3a23ab0bf4 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 16 Mar 2024 18:52:08 +0900 Subject: [PATCH 333/356] =?UTF-8?q?[Remove]=20Tag=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/tag/application/TagService.java | 11 ----------- .../com/ttubeog/domain/tag/domain/RoadTag.java | 6 ------ .../com/ttubeog/domain/tag/domain/SpotTag.java | 6 ------ .../com/ttubeog/domain/tag/domain/StoreTag.java | 6 ------ .../java/com/ttubeog/domain/tag/domain/Tag.java | 15 --------------- .../tag/domain/repository/TagRepository.java | 9 --------- .../domain/tag/presentation/TagController.java | 7 ------- 7 files changed, 60 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/tag/application/TagService.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/domain/RoadTag.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/domain/SpotTag.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/domain/StoreTag.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/domain/Tag.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/domain/repository/TagRepository.java delete mode 100644 src/main/java/com/ttubeog/domain/tag/presentation/TagController.java diff --git a/src/main/java/com/ttubeog/domain/tag/application/TagService.java b/src/main/java/com/ttubeog/domain/tag/application/TagService.java deleted file mode 100644 index d317f47e..00000000 --- a/src/main/java/com/ttubeog/domain/tag/application/TagService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ttubeog.domain.tag.application; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@Service -@Transactional(readOnly = true) -public class TagService { -} diff --git a/src/main/java/com/ttubeog/domain/tag/domain/RoadTag.java b/src/main/java/com/ttubeog/domain/tag/domain/RoadTag.java deleted file mode 100644 index dab31aaa..00000000 --- a/src/main/java/com/ttubeog/domain/tag/domain/RoadTag.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ttubeog.domain.tag.domain; - -import com.ttubeog.domain.common.BaseEntity; - -public class RoadTag extends BaseEntity { -} diff --git a/src/main/java/com/ttubeog/domain/tag/domain/SpotTag.java b/src/main/java/com/ttubeog/domain/tag/domain/SpotTag.java deleted file mode 100644 index 34276e03..00000000 --- a/src/main/java/com/ttubeog/domain/tag/domain/SpotTag.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ttubeog.domain.tag.domain; - -import com.ttubeog.domain.common.BaseEntity; - -public class SpotTag extends BaseEntity { -} diff --git a/src/main/java/com/ttubeog/domain/tag/domain/StoreTag.java b/src/main/java/com/ttubeog/domain/tag/domain/StoreTag.java deleted file mode 100644 index 46bb60d9..00000000 --- a/src/main/java/com/ttubeog/domain/tag/domain/StoreTag.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ttubeog.domain.tag.domain; - -import com.ttubeog.domain.common.BaseEntity; - -public class StoreTag extends BaseEntity { -} diff --git a/src/main/java/com/ttubeog/domain/tag/domain/Tag.java b/src/main/java/com/ttubeog/domain/tag/domain/Tag.java deleted file mode 100644 index 6b17553a..00000000 --- a/src/main/java/com/ttubeog/domain/tag/domain/Tag.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ttubeog.domain.tag.domain; - -import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; - -@Entity -public class Tag extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; -} diff --git a/src/main/java/com/ttubeog/domain/tag/domain/repository/TagRepository.java b/src/main/java/com/ttubeog/domain/tag/domain/repository/TagRepository.java deleted file mode 100644 index 2a132889..00000000 --- a/src/main/java/com/ttubeog/domain/tag/domain/repository/TagRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ttubeog.domain.tag.domain.repository; - -import com.ttubeog.domain.tag.domain.Tag; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface TagRepository extends JpaRepository { -} diff --git a/src/main/java/com/ttubeog/domain/tag/presentation/TagController.java b/src/main/java/com/ttubeog/domain/tag/presentation/TagController.java deleted file mode 100644 index 3e8ce154..00000000 --- a/src/main/java/com/ttubeog/domain/tag/presentation/TagController.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.tag.presentation; - -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class TagController { -} From 1304e3f459cf9e04f9467fe793e4e0dcdf9971cb Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 16 Mar 2024 18:52:28 +0900 Subject: [PATCH 334/356] =?UTF-8?q?[Remove]=20Sido=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/area/domain/SidoArea.java | 15 --------------- .../domain/repository/SidoAreaRepository.java | 9 --------- 2 files changed, 24 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/area/domain/SidoArea.java delete mode 100644 src/main/java/com/ttubeog/domain/area/domain/repository/SidoAreaRepository.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/SidoArea.java b/src/main/java/com/ttubeog/domain/area/domain/SidoArea.java deleted file mode 100644 index 8f51e936..00000000 --- a/src/main/java/com/ttubeog/domain/area/domain/SidoArea.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ttubeog.domain.area.domain; - -import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; - -@Entity -public class SidoArea extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; -} diff --git a/src/main/java/com/ttubeog/domain/area/domain/repository/SidoAreaRepository.java b/src/main/java/com/ttubeog/domain/area/domain/repository/SidoAreaRepository.java deleted file mode 100644 index e3b17ddf..00000000 --- a/src/main/java/com/ttubeog/domain/area/domain/repository/SidoAreaRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ttubeog.domain.area.domain.repository; - -import com.ttubeog.domain.area.domain.SidoArea; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface SidoAreaRepository extends JpaRepository { -} From 971168319e5381b342a6e5d28398abbf6e0d9af7 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 16 Mar 2024 18:52:38 +0900 Subject: [PATCH 335/356] =?UTF-8?q?[Remove]=20Sigg=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/area/domain/SiggArea.java | 15 --------------- .../domain/repository/SiggAreaRepository.java | 9 --------- 2 files changed, 24 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/area/domain/SiggArea.java delete mode 100644 src/main/java/com/ttubeog/domain/area/domain/repository/SiggAreaRepository.java diff --git a/src/main/java/com/ttubeog/domain/area/domain/SiggArea.java b/src/main/java/com/ttubeog/domain/area/domain/SiggArea.java deleted file mode 100644 index 2706ca0f..00000000 --- a/src/main/java/com/ttubeog/domain/area/domain/SiggArea.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ttubeog.domain.area.domain; - -import com.ttubeog.domain.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; - -@Entity -public class SiggArea extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; -} diff --git a/src/main/java/com/ttubeog/domain/area/domain/repository/SiggAreaRepository.java b/src/main/java/com/ttubeog/domain/area/domain/repository/SiggAreaRepository.java deleted file mode 100644 index b404e61d..00000000 --- a/src/main/java/com/ttubeog/domain/area/domain/repository/SiggAreaRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ttubeog.domain.area.domain.repository; - -import com.ttubeog.domain.area.domain.SiggArea; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface SiggAreaRepository extends JpaRepository { -} From 2b78cb2e5bc715f996f08017e8973d09c0bf1a91 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 16 Mar 2024 18:56:10 +0900 Subject: [PATCH 336/356] =?UTF-8?q?[Remove]=20AreaService,=20AreaControlle?= =?UTF-8?q?r=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/area/application/AreaService.java | 11 ----------- .../domain/area/presentation/AreaController.java | 7 ------- 2 files changed, 18 deletions(-) delete mode 100644 src/main/java/com/ttubeog/domain/area/application/AreaService.java delete mode 100644 src/main/java/com/ttubeog/domain/area/presentation/AreaController.java diff --git a/src/main/java/com/ttubeog/domain/area/application/AreaService.java b/src/main/java/com/ttubeog/domain/area/application/AreaService.java deleted file mode 100644 index 1c95ff76..00000000 --- a/src/main/java/com/ttubeog/domain/area/application/AreaService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ttubeog.domain.area.application; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@Service -@Transactional(readOnly = true) -public class AreaService { -} diff --git a/src/main/java/com/ttubeog/domain/area/presentation/AreaController.java b/src/main/java/com/ttubeog/domain/area/presentation/AreaController.java deleted file mode 100644 index d5f8f22e..00000000 --- a/src/main/java/com/ttubeog/domain/area/presentation/AreaController.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ttubeog.domain.area.presentation; - -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class AreaController { -} From 57d564f7719058b281d36820436cf496648b43b5 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Sat, 16 Mar 2024 19:33:15 +0900 Subject: [PATCH 337/356] =?UTF-8?q?[Chore]=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/benefit/dto/response/SaveBenefitRes.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java index 721cd729..b0a469a4 100644 --- a/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java +++ b/src/main/java/com/ttubeog/domain/benefit/dto/response/SaveBenefitRes.java @@ -32,13 +32,13 @@ public class SaveBenefitRes { private Boolean used; @Schema(description = "만료 여부", example = "false") - private Boolean expried; + private Boolean expired; @Schema(description = "혜택 저장 시간", example = "2024-01-12 09:30:50") private LocalDateTime createdAt; @Builder - public SaveBenefitRes(Long id, Long benefitId, Long storeId, String storeName, String content, BenefitType type, Boolean used, Boolean expried, LocalDateTime createdAt) { + public SaveBenefitRes(Long id, Long benefitId, Long storeId, String storeName, String content, BenefitType type, Boolean used, Boolean expired, LocalDateTime createdAt) { this.id = id; this.benefitId = benefitId; this.storeId = storeId; @@ -46,7 +46,7 @@ public SaveBenefitRes(Long id, Long benefitId, Long storeId, String storeName, S this.content = content; this.type = type; this.used = used; - this.expried = expried; + this.expired = expired; this.createdAt = createdAt; } } From 84bebf3be8b356ffe51ff9f10250ecb6caa3b922 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:21:08 +0900 Subject: [PATCH 338/356] =?UTF-8?q?[Hotfix]=20spot=20Controller=20findBySp?= =?UTF-8?q?otId=20API=20endpoint=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/presentation/SpotController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 8672a57f..0a77d53c 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -171,7 +171,7 @@ public ResponseEntity createSpot( @GetMapping("/{spotId}") public ResponseEntity findBySpotId( @CurrentUser HttpServletRequest request, - @RequestParam(name = "spotId") Long spotId + @PathVariable(name = "spotId") Long spotId ) throws JsonProcessingException { return spotService.findBySpotId(request, spotId); } From 87871de95ce73828221359b57ff4b463fb1ffd68 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:05:16 +0900 Subject: [PATCH 339/356] =?UTF-8?q?[Chore]=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/benefit/application/BenefitService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 38de8493..2a007b4d 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -69,7 +69,7 @@ public ApiResponse saveBenefit(HttpServletRequest request, Long benefitId) throw .content(benefit.getContent()) .type(benefit.getType()) .used(memberBenefit.getUsed()) - .expried(memberBenefit.getExpired()) + .expired(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) .build(); @@ -101,7 +101,7 @@ public ApiResponse useBenefit(HttpServletRequest request, Long benefitId) throws .storeId(benefit.getStore().getId()) .storeName(benefit.getStore().getName()) .used(memberBenefit.getUsed()) - .expried(memberBenefit.getExpired()) + .expired(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) .content(benefit.getContent()) .type(benefit.getType()) @@ -124,7 +124,7 @@ public ApiResponse findMyBenefit(HttpServletRequest request, Integer page) throw .storeId(memberBenefit.getBenefit().getStore().getId()) .storeName(memberBenefit.getBenefit().getStore().getName()) .used(memberBenefit.getUsed()) - .expried(memberBenefit.getExpired()) + .expired(memberBenefit.getExpired()) .createdAt(memberBenefit.getCreatedAt()) .content(memberBenefit.getBenefit().getContent()) .type(memberBenefit.getBenefit().getType()) From 1af00b2c3af96baa7fc22194ab88e3fc8b71abb5 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:11:06 +0900 Subject: [PATCH 340/356] =?UTF-8?q?[Remove]=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/benefit/application/BenefitService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java index 2a007b4d..41e11bb4 100644 --- a/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java +++ b/src/main/java/com/ttubeog/domain/benefit/application/BenefitService.java @@ -14,13 +14,11 @@ import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; import com.ttubeog.domain.member.exception.InvalidMemberException; -import com.ttubeog.domain.store.domain.repository.StoreRepository; import com.ttubeog.global.payload.ApiResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,7 +34,6 @@ public class BenefitService { private final MemberRepository memberRepository; private final BenefitRepository benefitRepository; private final MemberBenefitRepository memberBenefitRepository; - private final StoreRepository storeRepository; private final JwtTokenProvider jwtTokenProvider; //게임 성공 후 혜택 저장 From f1932f462e76876a3ac7d2f4a6568a7ac8433e4e Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:12:31 +0900 Subject: [PATCH 341/356] =?UTF-8?q?[Chore]=20API=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/benefit/presentation/BenefitController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java index 8f122153..7edc59f9 100644 --- a/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java +++ b/src/main/java/com/ttubeog/domain/benefit/presentation/BenefitController.java @@ -43,7 +43,7 @@ public ResponseEntity saveBenefit( @ApiResponse(responseCode = "200", description = "혜택 사용 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = SaveBenefitRes.class) ) } ), @ApiResponse(responseCode = "400", description = "혜택 사용 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @PatchMapping("{benefitId}/use") + @PatchMapping("/{benefitId}/use") public ResponseEntity useBenefit( HttpServletRequest request, @PathVariable(value = "benefitId") Long benefitId From 3841314375867e8cd3e7044d31399859b0a7cd15 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:29:01 +0900 Subject: [PATCH 342/356] =?UTF-8?q?[Chore]=20API=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/presentation/GuestBookController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 24a8fdb0..8681e681 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -22,7 +22,7 @@ @Tag(name = "GuestBook", description = "GuestBook API(방명록 API)") @RequiredArgsConstructor @RestController -@RequestMapping("api/v1/guestbook") +@RequestMapping("/api/v1/guestbook") public class GuestBookController { private final GuestBookService guestBookService; From 933c0b0e0be837a614c77ebcc43cc3e08eda866c Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:31:45 +0900 Subject: [PATCH 343/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/guestbook/application/GuestBookService.java | 3 --- .../domain/guestbook/presentation/GuestBookController.java | 1 - 2 files changed, 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 25a18311..654c159b 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.guestbook.application; -import com.ttubeog.domain.UuidImage.domain.UuidImage; import com.ttubeog.domain.UuidImage.domain.repository.UuidImageRepository; import com.ttubeog.domain.auth.security.JwtTokenProvider; import com.ttubeog.domain.aws.s3.AmazonS3Manager; @@ -32,9 +31,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; -import java.util.UUID; @RequiredArgsConstructor @Service diff --git a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java index 8681e681..24c41709 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java +++ b/src/main/java/com/ttubeog/domain/guestbook/presentation/GuestBookController.java @@ -17,7 +17,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; @Tag(name = "GuestBook", description = "GuestBook API(방명록 API)") @RequiredArgsConstructor From f50915344ff99368141b895e9fc59c24e6a2426a Mon Sep 17 00:00:00 2001 From: choeun7 <95676587+choeun7@users.noreply.github.com> Date: Fri, 22 Mar 2024 17:40:39 +0900 Subject: [PATCH 344/356] =?UTF-8?q?image=20=EC=A1=B0=ED=9A=8C=20endpoint?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ttubeog/domain/image/presentation/ImageController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index c5a64d46..c62fe462 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -86,7 +86,7 @@ public ResponseEntity createGuestBookImage( // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageBySpotId( @CurrentUser HttpServletRequest request, - @RequestParam Long spotId + @PathVariable Long spotId ) { return ResponseEntity.ok(imageService.findImageBySpotId(request, spotId)); } @@ -100,7 +100,7 @@ public ResponseEntity findImageBySpotId( // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByStoreId( @CurrentUser HttpServletRequest request, - @RequestParam Long storeId + @PathVariable Long storeId ) { return ResponseEntity.ok(imageService.findImageByStoreId(request, storeId)); } From 41d0da2be3f34d8b0cca2bece5fe4c6b5ed0262c Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:32:12 +0900 Subject: [PATCH 345/356] =?UTF-8?q?[Remove]=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/guestbook/application/GuestBookService.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java index 654c159b..c7b75766 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java +++ b/src/main/java/com/ttubeog/domain/guestbook/application/GuestBookService.java @@ -42,12 +42,6 @@ public class GuestBookService { private final MemberRepository memberRepository; private final SpotRepository spotRepository; private final StoreRepository storeRepository; - private final ImageRepository imageRepository; - private final UuidImageRepository uuidImageRepository; - - //private final ImageService imageService; - - private final AmazonS3Manager amazonS3Manager; private final JwtTokenProvider jwtTokenProvider; From 389110396e65581e4563d8766c895b3b57f08f46 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:34:32 +0900 Subject: [PATCH 346/356] =?UTF-8?q?[Chore]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=84=B8=EB=AF=B8=EC=BD=9C=EB=A1=A0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/guestbook/domain/GuestBookType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java index 241c544b..4d7b0d20 100644 --- a/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java +++ b/src/main/java/com/ttubeog/domain/guestbook/domain/GuestBookType.java @@ -5,5 +5,5 @@ @Getter public enum GuestBookType { SPOT, - STORE; + STORE } From 8d5454a6c1444f2b3405f529ab53833533ca6b28 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:41:24 +0900 Subject: [PATCH 347/356] =?UTF-8?q?[Chore]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=84=B8=EB=AF=B8=EC=BD=9C=EB=A1=A0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/road/domain/RoadType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/road/domain/RoadType.java b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java index 84e89108..cc623fb7 100644 --- a/src/main/java/com/ttubeog/domain/road/domain/RoadType.java +++ b/src/main/java/com/ttubeog/domain/road/domain/RoadType.java @@ -3,5 +3,5 @@ public enum RoadType { SPOT, - STORE; + STORE } From 70dc8bc57c68b32e10af01f863d8bd5ad71342ea Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:42:30 +0900 Subject: [PATCH 348/356] =?UTF-8?q?[Chore]=20API=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/road/presentation/RoadController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java index d913cd7a..57feb67c 100644 --- a/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java +++ b/src/main/java/com/ttubeog/domain/road/presentation/RoadController.java @@ -22,7 +22,7 @@ @Tag(name = "Road", description = "Road API(산책로 API)") @RequiredArgsConstructor @RestController -@RequestMapping("api/v1/road") +@RequestMapping("/api/v1/road") public class RoadController { private final RoadService roadService; From 02148b1d10364780a8878367b299fd4f417551e2 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:44:57 +0900 Subject: [PATCH 349/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ttubeog/domain/spot/application/SpotService.java | 2 -- src/main/java/com/ttubeog/domain/spot/domain/Spot.java | 6 ------ .../domain/spot/dto/request/CreateSpotRequestDto.java | 1 - .../ttubeog/domain/spot/dto/response/GetSpotDetailRes.java | 2 -- .../ttubeog/domain/spot/dto/response/SpotResponseDto.java | 2 -- .../ttubeog/domain/spot/presentation/SpotController.java | 1 - 6 files changed, 14 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 6791236e..96f77471 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -6,9 +6,7 @@ import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; -import com.ttubeog.domain.image.domain.ImageType; import com.ttubeog.domain.image.domain.repository.ImageRepository; -import com.ttubeog.domain.image.dto.request.CreateImageRequestDto; import com.ttubeog.domain.likes.domain.repository.LikesRepository; import com.ttubeog.domain.member.domain.Member; import com.ttubeog.domain.member.domain.repository.MemberRepository; diff --git a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java index eb178317..eb6e38ab 100644 --- a/src/main/java/com/ttubeog/domain/spot/domain/Spot.java +++ b/src/main/java/com/ttubeog/domain/spot/domain/Spot.java @@ -1,8 +1,6 @@ package com.ttubeog.domain.spot.domain; -import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; -import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.member.domain.Member; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; @@ -10,10 +8,6 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.apache.ibatis.annotations.Many; -import org.hibernate.annotations.Fetch; - -import java.util.List; @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter diff --git a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java index 82ce67f0..3362554b 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/request/CreateSpotRequestDto.java @@ -5,7 +5,6 @@ import lombok.Builder; import lombok.Getter; -import java.util.List; @Schema(description = "게시글 생성 DTO") @Getter diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java b/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java index 3ab61c14..b76f5aad 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/GetSpotDetailRes.java @@ -1,8 +1,6 @@ package com.ttubeog.domain.spot.dto.response; import com.fasterxml.jackson.annotation.JsonInclude; -import com.ttubeog.domain.benefit.domain.BenefitType; -import com.ttubeog.domain.store.domain.StoreType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java index e11b81b0..2971fa7f 100644 --- a/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java +++ b/src/main/java/com/ttubeog/domain/spot/dto/response/SpotResponseDto.java @@ -6,8 +6,6 @@ import lombok.Builder; import lombok.Getter; -import java.util.List; - @Getter @Builder diff --git a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java index 8672a57f..e0c2af54 100644 --- a/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java +++ b/src/main/java/com/ttubeog/domain/spot/presentation/SpotController.java @@ -1,7 +1,6 @@ package com.ttubeog.domain.spot.presentation; import com.fasterxml.jackson.core.JsonProcessingException; -import com.ttubeog.domain.guestbook.application.GuestBookService; import com.ttubeog.domain.likes.application.LikesService; import com.ttubeog.domain.member.exception.InvalidMemberException; import com.ttubeog.domain.spot.application.SpotService; From 0fe069d7e17ef9f0ffd27f6b194981635620b270 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:45:41 +0900 Subject: [PATCH 350/356] =?UTF-8?q?[Remove]=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index 96f77471..b8aa412e 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -44,9 +44,6 @@ public class SpotService { private final ImageRepository imageRepository; private final GuestBookRepository guestBookRepository; private final LikesRepository likesRepository; - private final BenefitRepository benefitRepository; - - private final ImageService imageService; private final JwtTokenProvider jwtTokenProvider; From 765a54bca5c01dddb7e719a41fb7cce55311515c Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:46:39 +0900 Subject: [PATCH 351/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ttubeog/domain/spot/application/SpotService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java index b8aa412e..9f817185 100644 --- a/src/main/java/com/ttubeog/domain/spot/application/SpotService.java +++ b/src/main/java/com/ttubeog/domain/spot/application/SpotService.java @@ -1,10 +1,8 @@ package com.ttubeog.domain.spot.application; import com.ttubeog.domain.auth.security.JwtTokenProvider; -import com.ttubeog.domain.benefit.domain.repository.BenefitRepository; import com.ttubeog.domain.guestbook.domain.GuestBook; import com.ttubeog.domain.guestbook.domain.repository.GuestBookRepository; -import com.ttubeog.domain.image.application.ImageService; import com.ttubeog.domain.image.domain.Image; import com.ttubeog.domain.image.domain.repository.ImageRepository; import com.ttubeog.domain.likes.domain.repository.LikesRepository; From 322e1285f35cc3d8a89fe8f2d7d1b1556241621b Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 22 Mar 2024 17:48:27 +0900 Subject: [PATCH 352/356] =?UTF-8?q?[Chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ttubeog/domain/store/domain/Store.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ttubeog/domain/store/domain/Store.java b/src/main/java/com/ttubeog/domain/store/domain/Store.java index a72a1a7f..1ce40f80 100644 --- a/src/main/java/com/ttubeog/domain/store/domain/Store.java +++ b/src/main/java/com/ttubeog/domain/store/domain/Store.java @@ -1,6 +1,5 @@ package com.ttubeog.domain.store.domain; -import com.ttubeog.domain.area.domain.DongArea; import com.ttubeog.domain.common.BaseEntity; import com.ttubeog.domain.member.domain.Member; import jakarta.persistence.Table; From 8825127daa2ef40fb8860f8f1f786f796f101f4b Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 22 Mar 2024 18:06:50 +0900 Subject: [PATCH 353/356] =?UTF-8?q?[Fix]=20ImageController=20Endpoint=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/image/presentation/ImageController.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index c62fe462..01723f85 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -82,7 +82,7 @@ public ResponseEntity createGuestBookImage( @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @GetMapping(value = "/{spotId}") + @GetMapping(value = "/spot/{spotId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageBySpotId( @CurrentUser HttpServletRequest request, @@ -96,7 +96,7 @@ public ResponseEntity findImageBySpotId( @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @GetMapping(value = "/{storeId}") + @GetMapping(value = "/store/{storeId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByStoreId( @CurrentUser HttpServletRequest request, @@ -110,7 +110,7 @@ public ResponseEntity findImageByStoreId( @ApiResponse(responseCode = "200", description = "이미지 조회 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ImageResponseDto.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 조회 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @GetMapping(value = "/{guestBookId}") + @GetMapping(value = "/guestbook/{guestBookId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByGuestBookId( @CurrentUser HttpServletRequest request, @@ -125,7 +125,7 @@ public ResponseEntity findImageByGuestBookId( @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @DeleteMapping(value = "/{spotId}") + @DeleteMapping(value = "/spot/{spotId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageBySpotId( @RequestParam Long spotId @@ -138,7 +138,7 @@ public ResponseEntity deleteImageBySpotId( @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @DeleteMapping(value = "/{storeId}") + @DeleteMapping(value = "/store/{storeId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByStoreId( @RequestParam Long storeId @@ -151,7 +151,7 @@ public ResponseEntity deleteImageByStoreId( @ApiResponse(responseCode = "200", description = "이미지 삭제 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), @ApiResponse(responseCode = "400", description = "이미지 삭제 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), }) - @DeleteMapping(value = "/{guestBookId}") + @DeleteMapping(value = "/guestbook/{guestBookId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByGuestBookId( @RequestParam Long guestBookId From 554624c2c2431292b02d8d0604f3ac061a911d61 Mon Sep 17 00:00:00 2001 From: choeun7 Date: Fri, 22 Mar 2024 18:09:19 +0900 Subject: [PATCH 354/356] [Fix] RequestParam -> PathVariable --- .../domain/image/presentation/ImageController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java index 01723f85..d9d3559b 100644 --- a/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java +++ b/src/main/java/com/ttubeog/domain/image/presentation/ImageController.java @@ -114,7 +114,7 @@ public ResponseEntity findImageByStoreId( // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity findImageByGuestBookId( @CurrentUser HttpServletRequest request, - @RequestParam Long guestBookId + @PathVariable Long guestBookId ) { return ResponseEntity.ok(imageService.findImageByGuestBookId(request, guestBookId)); } @@ -128,7 +128,7 @@ public ResponseEntity findImageByGuestBookId( @DeleteMapping(value = "/spot/{spotId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageBySpotId( - @RequestParam Long spotId + @PathVariable Long spotId ) { return ResponseEntity.ok(imageService.deleteImageBySpotId(spotId)); } @@ -141,7 +141,7 @@ public ResponseEntity deleteImageBySpotId( @DeleteMapping(value = "/store/{storeId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByStoreId( - @RequestParam Long storeId + @PathVariable Long storeId ) { return ResponseEntity.ok(imageService.deleteImageByStoreId(storeId)); } @@ -154,7 +154,7 @@ public ResponseEntity deleteImageByStoreId( @DeleteMapping(value = "/guestbook/{guestBookId}") // @ResponseStatus(value = HttpStatus.OK) public ResponseEntity deleteImageByGuestBookId( - @RequestParam Long guestBookId + @PathVariable Long guestBookId ) { return ResponseEntity.ok(imageService.deleteImageByGuestBookId(guestBookId)); } From fe2bb49e53d5f8bb27a4707c87e605e0660d54ad Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Mon, 6 May 2024 20:25:49 +0900 Subject: [PATCH 355/356] Create gradle-prod.yml --- .github/workflows/gradle-prod.yml | 116 ++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 .github/workflows/gradle-prod.yml diff --git a/.github/workflows/gradle-prod.yml b/.github/workflows/gradle-prod.yml new file mode 100644 index 00000000..7fad33c9 --- /dev/null +++ b/.github/workflows/gradle-prod.yml @@ -0,0 +1,116 @@ +name: Java CI with Gradle - Product + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + AWS_REGION: ap-northeast-2 + S3_BUCKET_NAME: s3-ttubeog + CODE_DEPLOY_APPLICATION_NAME: ttubeog-codedeploy + CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: ttubeog-deploy-group + + +permissions: + contents: read + +jobs: + build: + name: Build + runs-on: ubuntu-22.04 + + steps: + # 작업 엑세스 가능하게 $GITHUB_WORKSPACE에서 저장소를 체크아웃 + - name: Checkout branch + uses: actions/checkout@v3 + + # java 버전 세팅 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'zulu' + + # git ignore한 yml 파일들 github secret에서 복사해 오기 + - name: Copy secret + env: + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET_PROD }} + OCCUPY_LOGBACK_SECRET: ${{ secrets.OCCUPY_LOGBACK_SECRET }} + + OCCUPY_SECRET_DIR: ./src/main/resources + OCCUPY_LOGBACK_SECRET_DIR: ./src/main/resources + + OCCUPY_SECRET_DIR_FILE_NAME: application.yml + OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME: logback-test.xml + run: | + touch $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + touch $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + echo "$OCCUPY_SECRET" > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + echo "$OCCUPY_LOGBACK_SECRET" > $OCCUPY_LOGBACK_SECRET_DIR/$OCCUPY_LOGBACK_SECRET_DIR_FILE_NAME + + # gradlew 실행 권한 부여 + - name: Run chmod to make gradlew executable + run: chmod +x ./gradlew + shell: bash + + # Build -> jar 파일 생성 + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + - name: Upload Build artifacts + uses: actions/upload-artifact@v2 + with: + name: build-artifacts + path: | + build/libs/*.jar + + - name: Start redis-server + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY_PROD }} + host: ${{ secrets.EC2_HOST_PROD }} + username: ${{ secrets.EC2_USER_PROD }} + target: /home/ubuntu/app/spring_source + source: . + command: sudo systemctl start redis-server + + + + + deploy: + name: CD with SSH + needs: build + runs-on: ubuntu-22.04 + + steps: + - name: Download build artifacts + uses: actions/download-artifact@v2 + with: + name: build-artifacts + + # JAR 파일을 EC2에 배포하는 step + - name: SCP JAR to EC2 + uses: appleboy/scp-action@master + with: + key: ${{ secrets.EC2_KEY_PROD }} + host: ${{ secrets.EC2_HOST_PROD }} + username: ${{ secrets.EC2_USER_PROD }} + source: "*.jar" + target: "/home/ubuntu/app" + + # EC2에 SSH로 배포 커맨드를 입력하는 step + - name: Deploy SSH + uses: appleboy/ssh-action@master + with: + key: ${{ secrets.EC2_KEY_PROD }} + host: ${{ secrets.EC2_HOST_PROD }} + username: ${{ secrets.EC2_USER_PROD }} + # 기존 실행 중인 서버 종료 후 jar 파일 실행 + script: | + sudo fuser -k -n tcp 8080 + sleep 15 + sudo nohup java -jar /home/ubuntu/app/*.jar > ./nohup.out 2>&1 & From c3f1c067e7064f44462d7b72f9515f8ffe8b0264 Mon Sep 17 00:00:00 2001 From: Dustbox <53044223+sanggae4133@users.noreply.github.com> Date: Mon, 6 May 2024 20:26:04 +0900 Subject: [PATCH 356/356] Update gradle.yml --- .github/workflows/gradle.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9bd77c41..73fce744 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -36,7 +36,7 @@ jobs: # git ignore한 yml 파일들 github secret에서 복사해 오기 - name: Copy secret env: - OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET_DEV }} OCCUPY_LOGBACK_SECRET: ${{ secrets.OCCUPY_LOGBACK_SECRET }} OCCUPY_SECRET_DIR: ./src/main/resources @@ -71,9 +71,9 @@ jobs: - name: Start redis-server uses: appleboy/scp-action@master with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} + key: ${{ secrets.EC2_KEY_DEV }} + host: ${{ secrets.EC2_HOST_DEV }} + username: ${{ secrets.EC2_USER_DEV }} target: /home/ubuntu/app/spring_source source: . command: sudo systemctl start redis-server @@ -96,9 +96,9 @@ jobs: - name: SCP JAR to EC2 uses: appleboy/scp-action@master with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} + key: ${{ secrets.EC2_KEY_DEV }} + host: ${{ secrets.EC2_HOST_DEV }} + username: ${{ secrets.EC2_USER_DEV }} source: "*.jar" target: "/home/ubuntu/app" @@ -106,9 +106,9 @@ jobs: - name: Deploy SSH uses: appleboy/ssh-action@master with: - key: ${{ secrets.EC2_KEY }} - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} + key: ${{ secrets.EC2_KEY_DEV }} + host: ${{ secrets.EC2_HOST_DEV }} + username: ${{ secrets.EC2_USER_DEV }} # 기존 실행 중인 서버 종료 후 jar 파일 실행 script: | sudo fuser -k -n tcp 8080