From f10d9ea1df2764767b96b6496e1216fcc867b316 Mon Sep 17 00:00:00 2001 From: parkduhwan Date: Thu, 15 Aug 2024 14:51:39 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A4=EB=AE=A4=EB=8B=88=ED=8B=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C=EC=88=98=EC=99=80=20=EC=8B=9C=ED=81=90?= =?UTF-8?q?=EB=A6=AC=ED=8B=B0=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 커뮤니티에서 추천 메소드와 시큐리티 비밀번호 암호화 문제 해결 --- .../CustomAuthenticationProvider.java | 27 +++++ .../config/{ => security}/SecurityConfig.java | 9 +- .../controller/CommunityController.java | 108 ++++++++++++++---- .../healthylife/controller/Controller.java | 13 --- .../controller/JwtLoginAuthController.java | 18 +-- .../example/healthylife/dto/LoginRequest.java | 2 +- .../healthylife/entity/CommunityEntity.java | 13 ++- .../entity/CommunityRecommendEntity.java | 44 +++++++ .../CommunityRecommendRepository.java | 13 +++ .../repository/UserRepository.java | 3 +- .../healthylife/service/CommunityService.java | 83 ++++++++++---- .../healthylife/service/UserService.java | 10 +- 12 files changed, 267 insertions(+), 76 deletions(-) create mode 100644 src/main/java/com/example/healthylife/config/security/CustomAuthenticationProvider.java rename src/main/java/com/example/healthylife/config/{ => security}/SecurityConfig.java (88%) delete mode 100644 src/main/java/com/example/healthylife/controller/Controller.java create mode 100644 src/main/java/com/example/healthylife/entity/CommunityRecommendEntity.java create mode 100644 src/main/java/com/example/healthylife/repository/CommunityRecommendRepository.java diff --git a/src/main/java/com/example/healthylife/config/security/CustomAuthenticationProvider.java b/src/main/java/com/example/healthylife/config/security/CustomAuthenticationProvider.java new file mode 100644 index 0000000..0131c4a --- /dev/null +++ b/src/main/java/com/example/healthylife/config/security/CustomAuthenticationProvider.java @@ -0,0 +1,27 @@ +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; + +public class CustomAuthenticationProvider extends DaoAuthenticationProvider { + + public CustomAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { + setUserDetailsService(userDetailsService); + setPasswordEncoder(passwordEncoder); + } + + @Override + @SuppressWarnings("deprecation") + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws BadCredentialsException { + if (authentication.getCredentials() == null) { + throw new BadCredentialsException("No credentials provided"); + } + + String presentedPassword = authentication.getCredentials().toString(); + if (!getPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) { + throw new BadCredentialsException("현재 비밀번호가 userDetails 비밀번호와 맞지 않습니다."); + } + } +} diff --git a/src/main/java/com/example/healthylife/config/SecurityConfig.java b/src/main/java/com/example/healthylife/config/security/SecurityConfig.java similarity index 88% rename from src/main/java/com/example/healthylife/config/SecurityConfig.java rename to src/main/java/com/example/healthylife/config/security/SecurityConfig.java index fcac2a3..7760f30 100644 --- a/src/main/java/com/example/healthylife/config/SecurityConfig.java +++ b/src/main/java/com/example/healthylife/config/security/SecurityConfig.java @@ -1,8 +1,7 @@ -package com.example.healthylife.config; +package com.example.healthylife.config.security; import com.example.healthylife.config.jwt.JwtAuthenticationFilter; import com.example.healthylife.config.jwt.JwtUtil; -import com.example.healthylife.config.security.MyUserDetailsService; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.security.authentication.AuthenticationManager; @@ -25,7 +24,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() - .antMatchers("/user/userinfo", "/user/userupdate").authenticated() + .antMatchers("/community/register", "/community/update", "/community/delete/**","/community/recommend/**","/community/myCommunityContents").authenticated() + .antMatchers("/user/one","/user/delete","/user/update").authenticated() .anyRequest().permitAll() .and() .addFilterBefore(new JwtAuthenticationFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class); @@ -39,6 +39,7 @@ public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } + @Bean public DaoAuthenticationProvider authenticationProvider() { // DaoAuthenticationProvider를 설정하여 사용자 세부 정보와 비밀번호 암호화 설정을 Spring Security에 통합 @@ -47,4 +48,6 @@ public DaoAuthenticationProvider authenticationProvider() { authProvider.setPasswordEncoder(passwordEncoder); // 비밀번호 암호화 설정 return authProvider; } + + } diff --git a/src/main/java/com/example/healthylife/controller/CommunityController.java b/src/main/java/com/example/healthylife/controller/CommunityController.java index e6f140c..a65fdb6 100644 --- a/src/main/java/com/example/healthylife/controller/CommunityController.java +++ b/src/main/java/com/example/healthylife/controller/CommunityController.java @@ -2,35 +2,45 @@ import com.example.healthylife.config.jwt.JwtUtil; import com.example.healthylife.entity.CommunityEntity; +import com.example.healthylife.entity.CommunityRecommendEntity; +import com.example.healthylife.entity.UserEntity; +import com.example.healthylife.repository.CommunityRecommendRepository; +import com.example.healthylife.repository.CommunityRepository; +import com.example.healthylife.repository.UserRepository; import com.example.healthylife.service.CommunityService; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; - @RequestMapping("/community") @RestController @RequiredArgsConstructor public class CommunityController { + private final CommunityService communityService; private final JwtUtil jwtUtil; + private final UserRepository userRepository; + private final CommunityRecommendRepository communityRecommendRepository; + private final CommunityRepository communityRepository; @ApiOperation(value = "커뮤니티 글 전체 조회") @GetMapping("/all") public List communityList() { - List communityEntities = communityService.communityList(); - return communityEntities; + return communityService.communityList(); } @ApiOperation(value = "커뮤니티 내가 쓴 글 조회") @GetMapping("/myCommunityContents") public ResponseEntity> myCommunityContentsList(@RequestHeader("Authorization") String authorizationHeader) { - String jwtToken = jwtUtil.extractTokenFromHeader(authorizationHeader); if (jwtToken == null || !jwtUtil.validateToken(jwtToken)) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); @@ -45,19 +55,45 @@ public ResponseEntity> myCommunityContentsList(@RequestHea @ApiOperation(value = "커뮤니티 글 작성") @PostMapping("/register") - public CommunityEntity register(@RequestBody CommunityEntity communityEntity) { - return communityService.registerCommunity(communityEntity); + public ResponseEntity register(@RequestBody CommunityEntity communityEntity, Authentication authentication) { + String username = authentication.getName(); + UserEntity user = userRepository.findByUserId(username) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + // 커뮤니티 글 작성자 설정 + communityEntity.setUser(user); + // 커뮤니티 글 작성 + CommunityEntity savedCommunity = communityService.registerCommunity(communityEntity); + return ResponseEntity.status(HttpStatus.CREATED).body(savedCommunity); } + @ApiOperation(value = "커뮤니티 글 수정") @PutMapping("/update") - public CommunityEntity update(@RequestBody CommunityEntity communityEntity) { - return communityService.updateCommunity(communityEntity); + public ResponseEntity update(@RequestBody CommunityEntity updatedCommunityEntity, Authentication authentication) { + String username = authentication.getName(); // 인증된 사용자의 이름 (ID) + + try { + CommunityEntity updatedCommunity = communityService.updateCommunity( + updatedCommunityEntity.getCommunitySq(), + updatedCommunityEntity, + username + ); + return ResponseEntity.ok(updatedCommunity); + } catch (SecurityException e) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); // 403 Forbidden 응답 + } catch (RuntimeException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); // 404 Not Found 응답 + } } + @ApiOperation(value = "커뮤니티 글 삭제") @DeleteMapping("/delete/{communitySq}") - public ResponseEntity delete(@PathVariable("communitySq") Long communitySq) { + public ResponseEntity delete(@PathVariable("communitySq") Long communitySq, Authentication authentication) { + String username = authentication.getName(); // 인증된 사용자의 이름 (ID) + UserEntity user = userRepository.findByUserId(username) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + // 권한 체크 또는 작성자 확인 로직 추가 communityService.deleteBySq(communitySq); return ResponseEntity.noContent().build(); } @@ -65,28 +101,54 @@ public ResponseEntity delete(@PathVariable("communitySq") Long communitySq @ApiOperation(value = "커뮤니티 상세보기") @GetMapping("/communityDetail/{communitySq}") public ResponseEntity getCommunityBySq(@PathVariable("communitySq") Long communitySq) { - try { - Optional community = communityService.findCommunityBySq(communitySq); - if (community.isPresent()) { - return new ResponseEntity<>(community.get(), HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - } catch (Exception e) { - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } + Optional community = communityService.findCommunityBySq(communitySq); + return community.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).build()); } @ApiOperation(value = "커뮤니티 글 추천수") - @PostMapping("/recommend/{sq}") - public ResponseEntity communityRecommend(@PathVariable("sq") Long sq) { - long updatedCount = communityService.toggleRecommendation(sq); + @PostMapping("/recommend/{communitySq}") + public ResponseEntity communityRecommend(@PathVariable("communitySq") Long communitySq, + @RequestHeader("Authorization") String authorizationHeader) { + String jwtToken = jwtUtil.extractTokenFromHeader(authorizationHeader); + if (jwtToken == null || !jwtUtil.validateToken(jwtToken)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + String username = jwtUtil.getUserId(jwtToken); + UserEntity user = userRepository.findByUserId(username) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + + long updatedCount = communityService.toggleRecommendation(communitySq, user.getUserSq()); return ResponseEntity.ok(updatedCount); } + @ApiOperation(value = "커뮤니티 글 추천 여부 확인") + @GetMapping("/recommend/check/{communitySq}") + public ResponseEntity> checkRecommendation( + @PathVariable("communitySq") Long communitySq, + @RequestHeader("Authorization") String authorizationHeader) { + + // JWT 토큰을 통해 사용자 정보 추출 + String jwtToken = jwtUtil.extractTokenFromHeader(authorizationHeader); + if (jwtToken == null || !jwtUtil.validateToken(jwtToken)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + // 사용자 정보로 유저 ID 가져오기 + String username = jwtUtil.getUserId(jwtToken); + UserEntity user = userRepository.findByUserId(username) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + + // 사용자가 해당 커뮤니티 글을 추천했는지 여부 확인 + boolean hasRecommended = communityService.hasUserRecommended(communitySq, user.getUserSq()); + + // 추천 여부를 포함한 응답 반환 + return ResponseEntity.ok(Collections.singletonMap("hasRecommended", hasRecommended)); + } + + @ApiOperation(value = "커뮤니티 글 조회수") @PostMapping("/view/{sq}") - public ResponseEntity Communityview(@PathVariable("sq") Long sq) { + public ResponseEntity communityView(@PathVariable("sq") Long sq) { communityService.incrementview(sq); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/example/healthylife/controller/Controller.java b/src/main/java/com/example/healthylife/controller/Controller.java deleted file mode 100644 index b293f9f..0000000 --- a/src/main/java/com/example/healthylife/controller/Controller.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.healthylife.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class Controller { - - @GetMapping("/") - public String home() { - return "hello"; - } -} diff --git a/src/main/java/com/example/healthylife/controller/JwtLoginAuthController.java b/src/main/java/com/example/healthylife/controller/JwtLoginAuthController.java index c6ea372..26d281f 100644 --- a/src/main/java/com/example/healthylife/controller/JwtLoginAuthController.java +++ b/src/main/java/com/example/healthylife/controller/JwtLoginAuthController.java @@ -28,16 +28,15 @@ public class JwtLoginAuthController { private final AuthenticationManager authenticationManager; private final JwtUtil jwtUtil; - private final JwtAuthService jwtAuthService; private final ObjectMapper objectMapper; @ApiOperation("로그인") @PostMapping("/authenticate") - public ResponseEntity authenticate(@RequestBody LoginRequest loginRequest){ + public ResponseEntity authenticate(@RequestBody LoginRequest loginRequest) { try { // 사용자 이름(아이디)과 비밀번호로 인증 Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); + new UsernamePasswordAuthenticationToken(loginRequest.getUserId(), loginRequest.getPassword())); // 인증 성공하면 JWT 토큰 생성 String accessToken = jwtUtil.createAccessToken(UserEntity.builder() .userId(authentication.getName()) @@ -45,21 +44,24 @@ public ResponseEntity authenticate(@RequestBody LoginRequest loginReques String refreshToken = jwtUtil.createRefreshToken(UserEntity.builder() .userId(authentication.getName()) .build()); - jwtAuthService.addRefreshToken(refreshToken, loginRequest.getUsername()); - Map result = Map.of("access-token", accessToken, - "refresh-token", refreshToken); + Map result = Map.of( + "access-token", accessToken, + "refresh-token", refreshToken, + "userId", authentication.getName() + ); return ResponseEntity.ok() .body(objectMapper.writeValueAsString(result)); - } catch (UsernameNotFoundException | BadCredentialsException exception){ + } catch (UsernameNotFoundException | BadCredentialsException exception) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED) .body("아이디/비밀번호가 맞지 않습니다."); } catch (Exception e) { - log.error("authenticate failed! - username: {}, password: {}", loginRequest.getUsername(), loginRequest.getPassword(), e); + log.error("authenticate failed! - username: {}, password: {}", loginRequest.getUserId(), loginRequest.getPassword(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Exception : " + e.getMessage()); } } + // 현재 사용안함 // @GetMapping("/refresh") // public ResponseEntity refresh(@RequestParam("refresh-token") String refreshToken){ diff --git a/src/main/java/com/example/healthylife/dto/LoginRequest.java b/src/main/java/com/example/healthylife/dto/LoginRequest.java index c471e8b..6c0eea0 100644 --- a/src/main/java/com/example/healthylife/dto/LoginRequest.java +++ b/src/main/java/com/example/healthylife/dto/LoginRequest.java @@ -8,7 +8,7 @@ @Getter @Setter public class LoginRequest { - private String username; + private String userId; private String password; diff --git a/src/main/java/com/example/healthylife/entity/CommunityEntity.java b/src/main/java/com/example/healthylife/entity/CommunityEntity.java index 6974abf..43a80a3 100644 --- a/src/main/java/com/example/healthylife/entity/CommunityEntity.java +++ b/src/main/java/com/example/healthylife/entity/CommunityEntity.java @@ -67,12 +67,15 @@ public CommunityEntity(long communitySq, String communityTitle, String community this.user = user; } - // 추천수 - public void toggleRecommendation(boolean currentlyRecommended) { - if (currentlyRecommended) { + // 추천수 증가 메서드 + public void incrementRecommendationCount() { + this.communityRecommend++; + } + + // 추천수 감소 메서드 + public void decrementRecommendationCount() { + if (this.communityRecommend > 0) { this.communityRecommend--; - } else { - this.communityRecommend++; } } diff --git a/src/main/java/com/example/healthylife/entity/CommunityRecommendEntity.java b/src/main/java/com/example/healthylife/entity/CommunityRecommendEntity.java new file mode 100644 index 0000000..81ca3b8 --- /dev/null +++ b/src/main/java/com/example/healthylife/entity/CommunityRecommendEntity.java @@ -0,0 +1,44 @@ +package com.example.healthylife.entity; + +import javax.persistence.*; + +import com.example.healthylife.entity.CommunityEntity; +import com.example.healthylife.entity.UserEntity; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Setter +@Getter +@Entity +@Table(name = "community_recommend") +@NoArgsConstructor +//커뮤니티 추천수 엔티티 +public class CommunityRecommendEntity implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "community_id", nullable = false) + private CommunityEntity community; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private UserEntity user; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + public CommunityRecommendEntity(CommunityEntity community, UserEntity user) { + this.community = community; + this.user = user; + this.createdAt = LocalDateTime.now(); + } + +} diff --git a/src/main/java/com/example/healthylife/repository/CommunityRecommendRepository.java b/src/main/java/com/example/healthylife/repository/CommunityRecommendRepository.java new file mode 100644 index 0000000..0107dba --- /dev/null +++ b/src/main/java/com/example/healthylife/repository/CommunityRecommendRepository.java @@ -0,0 +1,13 @@ +package com.example.healthylife.repository; + +import com.example.healthylife.entity.CommunityEntity; +import com.example.healthylife.entity.CommunityRecommendEntity; +import com.example.healthylife.entity.UserEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface CommunityRecommendRepository extends JpaRepository { + boolean existsByCommunityAndUser(CommunityEntity community, UserEntity user); + Optional findByCommunityAndUser(CommunityEntity community, UserEntity user); +} diff --git a/src/main/java/com/example/healthylife/repository/UserRepository.java b/src/main/java/com/example/healthylife/repository/UserRepository.java index 5c4e2c3..6307ce2 100644 --- a/src/main/java/com/example/healthylife/repository/UserRepository.java +++ b/src/main/java/com/example/healthylife/repository/UserRepository.java @@ -2,9 +2,10 @@ import com.example.healthylife.entity.UserEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.Optional; - +@Repository public interface UserRepository extends JpaRepository { Optional findByUserId(String userId); diff --git a/src/main/java/com/example/healthylife/service/CommunityService.java b/src/main/java/com/example/healthylife/service/CommunityService.java index e4cfed2..014163f 100644 --- a/src/main/java/com/example/healthylife/service/CommunityService.java +++ b/src/main/java/com/example/healthylife/service/CommunityService.java @@ -2,13 +2,15 @@ import com.example.healthylife.entity.CommunityCommentsEntity; import com.example.healthylife.entity.CommunityEntity; +import com.example.healthylife.entity.CommunityRecommendEntity; +import com.example.healthylife.entity.UserEntity; +import com.example.healthylife.repository.CommunityRecommendRepository; import com.example.healthylife.repository.CommunityRepository; import com.example.healthylife.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - import java.util.List; import java.util.Optional; @@ -17,36 +19,52 @@ public class CommunityService { private final CommunityRepository communityRepository; + private final CommunityRecommendRepository communityRecommendRepository; + private final UserRepository userRepository; private final CommunityCommentsService communityCommentsService; - - //글전체조회 + // 글 전체 조회 public List communityList() { return communityRepository.findAll(); } - //커뮤니티 글 작성 + // 커뮤니티 글 작성 public CommunityEntity registerCommunity(CommunityEntity communityEntity) { return communityRepository.save(communityEntity); } - //커뮤니티 글 수정 + // 커뮤니티 글 수정 @Transactional - public CommunityEntity updateCommunity(CommunityEntity communityEntity) { - return communityRepository.save(communityEntity); + public CommunityEntity updateCommunity(Long communityId, CommunityEntity updatedCommunityEntity, String username) { + UserEntity user = userRepository.findByUserId(username) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + CommunityEntity existingCommunity = communityRepository.findById(communityId) + .orElseThrow(() -> new RuntimeException("커뮤니티 글이 없습니다.")); + // 권한 체크: 현재 로그인한 사용자가 작성자와 동일한지 확인 + if (!existingCommunity.getUser().getUserId().equals(username)) { + throw new SecurityException("작성자만 수정할 수 있습니다."); + } + // 커뮤니티 글의 내용 업데이트 + if (updatedCommunityEntity.getCommunityTitle() != null) { + existingCommunity.setCommunityTitle(updatedCommunityEntity.getCommunityTitle()); + } + if (updatedCommunityEntity.getCommunityContents() != null) { + existingCommunity.setCommunityContents(updatedCommunityEntity.getCommunityContents()); + } + return communityRepository.save(existingCommunity); } - //커뮤니티 글 삭제 + // 커뮤니티 글 삭제 public void deleteBySq(long communitySq) { communityRepository.deleteById(communitySq); } - //커뮤니티 내가 쓴글 조회 + // 커뮤니티 내가 쓴 글 조회 public List findMyContents(String userId) { return communityRepository.findByUserUserId(userId); } - //커뮤니티 단일조회 + // 커뮤니티 단일 조회 public Optional findCommunityBySq(Long communitySq) { Optional community = communityRepository.findByCommunitySq(communitySq); community.ifPresent(c -> { @@ -56,24 +74,49 @@ public Optional findCommunityBySq(Long communitySq) { return community; } - //커뮤니티 추천수 + // 커뮤니티 추천수 @Transactional - public long toggleRecommendation(Long sq) { - CommunityEntity community = communityRepository.findById(sq) + public long toggleRecommendation(Long communitySq, Long userId) { + // 커뮤니티 및 사용자 엔티티 조회 + CommunityEntity community = communityRepository.findById(communitySq) .orElseThrow(() -> new RuntimeException("커뮤니티가 없습니다.")); - - boolean isRecommended = community.getCommunityRecommend() > 0; - community.toggleRecommendation(isRecommended); + UserEntity user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + + // 추천 여부 확인 + boolean alreadyRecommended = communityRecommendRepository.existsByCommunityAndUser(community, user); + + if (alreadyRecommended) { + CommunityRecommendEntity recommendation = communityRecommendRepository.findByCommunityAndUser(community, user) + .orElseThrow(() -> new RuntimeException("추천 기록이 없습니다.")); + communityRecommendRepository.delete(recommendation); + community.decrementRecommendationCount(); + } else { + CommunityRecommendEntity recommendation = new CommunityRecommendEntity(community, user); + communityRecommendRepository.save(recommendation); + community.incrementRecommendationCount(); + } + + // 업데이트된 커뮤니티 저장 CommunityEntity updatedCommunity = communityRepository.save(community); return updatedCommunity.getCommunityRecommend(); } + // 사용자가 특정 커뮤니티 글에 대해 추천했는지 여부 확인 + public boolean hasUserRecommended(Long communitySq, Long userId) { + // 커뮤니티 및 사용자 엔티티 조회 + CommunityEntity community = communityRepository.findById(communitySq) + .orElseThrow(() -> new RuntimeException("커뮤니티가 없습니다.")); + UserEntity user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("유저가 없습니다.")); + // 추천 여부 확인 + return communityRecommendRepository.existsByCommunityAndUser(community, user); + } + + // 커뮤니티 조회수 @Transactional public void incrementview(Long communitySq) { communityRepository.incrementCommunityview(communitySq); } - - -} - +} \ No newline at end of file diff --git a/src/main/java/com/example/healthylife/service/UserService.java b/src/main/java/com/example/healthylife/service/UserService.java index ea36f8c..bfcb2fe 100644 --- a/src/main/java/com/example/healthylife/service/UserService.java +++ b/src/main/java/com/example/healthylife/service/UserService.java @@ -48,8 +48,14 @@ public UserEntity updateUser(UserEntity userEntity) { if (Objects.nonNull(userEntity.getUserEmail()) && !"".equalsIgnoreCase(userEntity.getUserEmail())) { resultEntityBuilder.userEmail(userEntity.getUserEmail()); } - if (Objects.nonNull(userEntity.getUserPw()) && !"".equalsIgnoreCase(userEntity.getUserPw())) { - resultEntityBuilder.userPw(passwordEncoder.encode(userEntity.getUserPw())); + if (Objects.nonNull(userEntity.getUserPhone()) && !"".equalsIgnoreCase(userEntity.getUserPhone())) { + resultEntityBuilder.userPhone(userEntity.getUserPhone()); + } + if (Objects.nonNull(userEntity.getUserAddress()) && !"".equalsIgnoreCase(userEntity.getUserAddress())) { + resultEntityBuilder.userAddress(userEntity.getUserAddress()); + } + if (userEntity.getUserAge() != null) { // userAge는 long이므로 null 체크가 필요 없으나, valid value check + resultEntityBuilder.userAge(userEntity.getUserAge()); } // 수정된 사용자 정보 저장 UserEntity updatedUser = resultEntityBuilder.build();