diff --git a/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTFilter.java b/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTFilter.java index 1698608..9f7e2c9 100644 --- a/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTFilter.java +++ b/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTFilter.java @@ -5,7 +5,6 @@ import io.jsonwebtoken.ExpiredJwtException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; -import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -58,12 +57,13 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } - - + Long userId = jwtUtil.getId(accessToken); String username = jwtUtil.getUsername(accessToken); String role = jwtUtil.getRole(accessToken); String name=jwtUtil.getName(accessToken); + UserDTO userDTO = UserDTO.builder() + .id(userId) .name(name) .username(username) .role(role) diff --git a/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTUtil.java b/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTUtil.java index 88ee472..c2dd261 100644 --- a/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTUtil.java +++ b/src/main/java/com/bamboo/log/domain/user/jwt/service/JWTUtil.java @@ -43,8 +43,13 @@ public String getCategory(String token) { public String getName(String token){ return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("name", String.class); } - public String createJwt(String category,String name,String username, String role, Long expiredMs) { + public Long getId(String token){ + return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("id", Long.class); + } + + public String createJwt(Long id, String category,String name,String username, String role, Long expiredMs) { return Jwts.builder() + .claim("id", id) .claim("category",category) .claim("username", username) .claim("name",name) diff --git a/src/main/java/com/bamboo/log/domain/user/oauth/dto/CustomOAuth2User.java b/src/main/java/com/bamboo/log/domain/user/oauth/dto/CustomOAuth2User.java index bb7502a..29e2adb 100644 --- a/src/main/java/com/bamboo/log/domain/user/oauth/dto/CustomOAuth2User.java +++ b/src/main/java/com/bamboo/log/domain/user/oauth/dto/CustomOAuth2User.java @@ -46,4 +46,6 @@ public String getUsername() { return userDTO.getUsername(); } + public Long getId() { return userDTO.getId(); } + } \ No newline at end of file diff --git a/src/main/java/com/bamboo/log/domain/user/oauth/dto/UserDTO.java b/src/main/java/com/bamboo/log/domain/user/oauth/dto/UserDTO.java index efda413..54f3499 100644 --- a/src/main/java/com/bamboo/log/domain/user/oauth/dto/UserDTO.java +++ b/src/main/java/com/bamboo/log/domain/user/oauth/dto/UserDTO.java @@ -8,6 +8,7 @@ @Builder @Getter public class UserDTO { + private Long id; private String name; private String username; private String role; diff --git a/src/main/java/com/bamboo/log/domain/user/oauth/entity/UserEntity.java b/src/main/java/com/bamboo/log/domain/user/oauth/entity/UserEntity.java index 2a3be77..03b88bc 100644 --- a/src/main/java/com/bamboo/log/domain/user/oauth/entity/UserEntity.java +++ b/src/main/java/com/bamboo/log/domain/user/oauth/entity/UserEntity.java @@ -1,5 +1,6 @@ package com.bamboo.log.domain.user.oauth.entity; +import com.bamboo.log.juksoon.domain.Juksoon; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; @@ -24,6 +25,9 @@ public class UserEntity { private String role; private String profile_img_url; + @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) + private Juksoon juksooni; + @Builder public UserEntity(String username, String name, String email, String role,String profile_img_url) { this.username = username; diff --git a/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomOAuth2UserService.java b/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomOAuth2UserService.java index b7f7c02..93fcb76 100644 --- a/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomOAuth2UserService.java +++ b/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomOAuth2UserService.java @@ -49,6 +49,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic userRepository.save(userEntity); UserDTO userDTO = UserDTO.builder() + .id(userEntity.getId()) .username(username) .name(oAuth2Response.getName()) .role("ROLE_USER") @@ -57,6 +58,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic return new CustomOAuth2User(userDTO); } else { UserDTO userDTO = UserDTO.builder() + .id(existData.getId()) .username(existData.getUsername()) .name(existData.getName()) .role(existData.getRole()) diff --git a/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomSuccessHandler.java b/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomSuccessHandler.java index f82af92..c91ce65 100644 --- a/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomSuccessHandler.java +++ b/src/main/java/com/bamboo/log/domain/user/oauth/service/CustomSuccessHandler.java @@ -30,6 +30,7 @@ public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { CustomOAuth2User customUserDetails = (CustomOAuth2User) authentication.getPrincipal(); + Long userId = customUserDetails.getId(); String name=customUserDetails.getName(); String username = customUserDetails.getUsername(); Collection authorities = authentication.getAuthorities(); @@ -37,8 +38,8 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo GrantedAuthority auth = iterator.next(); String role = auth.getAuthority(); - String refreshToken = jwtUtil.createJwt("refresh",name,username, role, 1800000L); - String accessToken = jwtUtil.createJwt("access",name,username, role, 1209600000L); + String refreshToken = jwtUtil.createJwt(userId,"refresh", name, username, role, 1800000L); + String accessToken = jwtUtil.createJwt(userId,"access", name, username, role, 1209600000L); addRefreshEntity(name, username, refreshToken, 1209600000L); response.addCookie(createCookie("refresh", refreshToken)); response.addCookie(UnScretCreateCookie("access", accessToken)); diff --git a/src/main/java/com/bamboo/log/domain/user/refresh/service/ProcessTokenReissueImpl.java b/src/main/java/com/bamboo/log/domain/user/refresh/service/ProcessTokenReissueImpl.java index 0e123ae..477002c 100644 --- a/src/main/java/com/bamboo/log/domain/user/refresh/service/ProcessTokenReissueImpl.java +++ b/src/main/java/com/bamboo/log/domain/user/refresh/service/ProcessTokenReissueImpl.java @@ -57,13 +57,13 @@ public ResponseEntity reissue(HttpServletRequest request, HttpServletResponse log.error("리프레시 토큰이 존재하지 않습니다. token: {}", refresh); return new ResponseEntity<>("invalid refresh token", HttpStatus.BAD_REQUEST); } - + Long userId = jwtUtil.getId(refresh); String name = jwtUtil.getName(refresh); String username = jwtUtil.getUsername(refresh); String role = jwtUtil.getRole(refresh); - String newAccess = jwtUtil.createJwt("access", name, username , role, 1800000L); - String newRefresh = jwtUtil.createJwt("refresh", name, username, role, 1209600000L); + String newAccess = jwtUtil.createJwt(userId,"access", name, username , role, 1800000L); + String newRefresh = jwtUtil.createJwt(userId,"refresh", name, username, role, 1209600000L); refreshRepository.deleteByToken(refresh); addRefreshEntity(name,username,role,1209600000L); diff --git a/src/main/java/com/bamboo/log/juksoon/controller/JuksoonController.java b/src/main/java/com/bamboo/log/juksoon/controller/JuksoonController.java new file mode 100644 index 0000000..b96dd38 --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/controller/JuksoonController.java @@ -0,0 +1,46 @@ +package com.bamboo.log.juksoon.controller; + +import com.bamboo.log.domain.user.oauth.dto.CustomOAuth2User; +import com.bamboo.log.juksoon.dto.JuksooniResponse; +import com.bamboo.log.juksoon.service.JuksoonService; +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.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping("/api/juksooni") +@RequiredArgsConstructor +@Tag(name = "Juksooni", description = "죽순이 분양 관련 API") +public class JuksoonController { + private final JuksoonService juksoonService; + + @PostMapping("/adopt") + @Operation(summary = "죽순이 분양", description = "JWT 토큰이 필요합니다.") + public ResponseEntity adoptJuksooni( + @AuthenticationPrincipal CustomOAuth2User customOAuth2User) { + + Long userId = customOAuth2User.getId(); + JuksooniResponse response = juksoonService.adoptJuksooni(userId); + return ResponseEntity.status(HttpStatus.CREATED).body(response); + } + + @GetMapping("/status") + @Operation(summary = "죽순이 분양 여부 조회", description = "JWT 토큰이 필요합니다.") + public ResponseEntity checkJuksooniStatus( + @AuthenticationPrincipal CustomOAuth2User customOAuth2User) { + + Long userId = customOAuth2User.getId(); + JuksooniResponse response = juksoonService.checkJuksooniStatus(userId); + + return ResponseEntity.ok(response); + + } +} \ No newline at end of file diff --git a/src/main/java/com/bamboo/log/juksoon/domain/Juksoon.java b/src/main/java/com/bamboo/log/juksoon/domain/Juksoon.java new file mode 100644 index 0000000..bd8dfcc --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/domain/Juksoon.java @@ -0,0 +1,22 @@ +package com.bamboo.log.juksoon.domain; + +import com.bamboo.log.domain.user.oauth.entity.UserEntity; +import jakarta.persistence.*; +import lombok.*; + +@Getter +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "juksooni") +@Builder +public class Juksoon { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne + @JoinColumn(name = "user_id", nullable = false, unique = true) + private UserEntity user; + +} diff --git a/src/main/java/com/bamboo/log/juksoon/dto/JuksooniResponse.java b/src/main/java/com/bamboo/log/juksoon/dto/JuksooniResponse.java new file mode 100644 index 0000000..cd4fe9b --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/dto/JuksooniResponse.java @@ -0,0 +1,8 @@ +package com.bamboo.log.juksoon.dto; + +import org.springframework.http.HttpStatus; + +public record JuksooniResponse( + HttpStatus status, + boolean hasJuksooni +) { } diff --git a/src/main/java/com/bamboo/log/juksoon/repository/JuksoonRepository.java b/src/main/java/com/bamboo/log/juksoon/repository/JuksoonRepository.java new file mode 100644 index 0000000..8bf6a64 --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/repository/JuksoonRepository.java @@ -0,0 +1,9 @@ +package com.bamboo.log.juksoon.repository; + +import com.bamboo.log.juksoon.domain.Juksoon; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface JuksoonRepository extends JpaRepository { + boolean existsByUserId(Long userId); + +} diff --git a/src/main/java/com/bamboo/log/juksoon/service/JuksoonService.java b/src/main/java/com/bamboo/log/juksoon/service/JuksoonService.java new file mode 100644 index 0000000..daf9999 --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/service/JuksoonService.java @@ -0,0 +1,8 @@ +package com.bamboo.log.juksoon.service; + +import com.bamboo.log.juksoon.dto.JuksooniResponse; + +public interface JuksoonService { + JuksooniResponse adoptJuksooni(Long userId); + JuksooniResponse checkJuksooniStatus(Long userId); +} diff --git a/src/main/java/com/bamboo/log/juksoon/service/JuksoonServiceImpl.java b/src/main/java/com/bamboo/log/juksoon/service/JuksoonServiceImpl.java new file mode 100644 index 0000000..f866361 --- /dev/null +++ b/src/main/java/com/bamboo/log/juksoon/service/JuksoonServiceImpl.java @@ -0,0 +1,56 @@ +package com.bamboo.log.juksoon.service; + +import com.bamboo.log.domain.user.oauth.entity.UserEntity; +import com.bamboo.log.domain.user.oauth.repository.UserRepository; +import com.bamboo.log.juksoon.domain.Juksoon; +import com.bamboo.log.juksoon.dto.JuksooniResponse; +import com.bamboo.log.juksoon.repository.JuksoonRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class JuksoonServiceImpl implements JuksoonService{ + + private final JuksoonRepository juksoonRepository; + private final UserRepository userRepository; + + // 죽순이 분양 로직 + @Override + @Transactional + public JuksooniResponse adoptJuksooni(Long userId) { + if (userId == null) { + throw new IllegalArgumentException("유저 ID가 null입니다."); + } + + // 이미 죽순이를 분양받았는지 확인 + if (juksoonRepository.existsByUserId(userId)) { + return new JuksooniResponse(HttpStatus.CONFLICT, false); + } + + // 유저 조회 + UserEntity user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("해당 유저를 찾을 수 없습니다.")); + + // 죽순이 생성 및 저장 + Juksoon juksoon = Juksoon.builder() + .user(user) + .build(); + juksoonRepository.save(juksoon); + + return new JuksooniResponse(HttpStatus.CREATED, true); + } + + // 죽순이 분양 여부 조회 로직 + @Override + @Transactional(readOnly = true) + public JuksooniResponse checkJuksooniStatus(Long userId) { + boolean hasJuksooni = juksoonRepository.existsByUserId(userId); + + return new JuksooniResponse(HttpStatus.OK, hasJuksooni); + } +}