Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#81] JWT 토큰으로 유저 정보 가져오도록 수정 #85

Merged
merged 1 commit into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import com.hobak.happinessql.domain.activity.application.*;
import com.hobak.happinessql.domain.activity.converter.ActivityConverter;
import com.hobak.happinessql.domain.activity.dto.*;
import com.hobak.happinessql.domain.user.application.UserFindService;
import com.hobak.happinessql.domain.user.domain.User;
import com.hobak.happinessql.global.response.DataResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

@Tag(name="Activity", description = "활동 관련 REST API에 대한 명세를 제공합니다.")
Expand All @@ -20,17 +24,22 @@ public class ActivityController {
private final ActivityDeleteService activityDeleteService;
private final ActivityUpdateService activityUpdateService;
private final ActivitySearchService activitySearchService;
private final UserFindService userFindService;

@Operation(summary = "활동 리스트 조회", description = "유저가 가지고 있는 활동 목록을 조회합니다. 행복 기록 생성 시 활동 선택 창에서 사용하는 API입니다.")
@GetMapping
public DataResponseDto<ActivityListResponseDto> getActivities(@RequestParam Long userId) {
public DataResponseDto<ActivityListResponseDto> getActivities(@AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
ActivityListResponseDto response = activityListService.getActivities(userId);
return DataResponseDto.of(response, "사용자의 모든 카테고리별 활동을 성공적으로 조회했습니다.");
}

@Operation(summary = "활동 추가", description = "기타 카테고리에 활동을 추가합니다.")
@PostMapping
public DataResponseDto<ActivityResponseDto> createActivity(@RequestBody ActivityCreateRequestDto requestDto, @RequestParam Long userId){
public DataResponseDto<ActivityResponseDto> createActivity(@RequestBody ActivityCreateRequestDto requestDto, @AuthenticationPrincipal UserDetails userDetails){
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
ActivityResponseDto responseDto = activityCreateService.createActivity(requestDto,userId);
return DataResponseDto.of(responseDto,"활동을 성공적으로 추가했습니다.");
}
Expand All @@ -52,7 +61,9 @@ public DataResponseDto<ActivityUpdateResponseDto> updateActicity(@PathVariable L

@Operation(summary = "활동 검색", description = "유저가 갖고 있는 활동을 검색합니다. (활동의 description에 있는 내용은 아직 검색되지 않습니다.)")
@PostMapping("/search")
public DataResponseDto<ActivitySearchResponseDto> searchActivities(@RequestBody ActivitySearchRequestDto requestDto, @RequestParam Long userId) {
public DataResponseDto<ActivitySearchResponseDto> searchActivities(@RequestBody ActivitySearchRequestDto requestDto, @AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
ActivitySearchResponseDto responseDto = activitySearchService.searchActivities(requestDto.getSearch(), userId);
return DataResponseDto.of(responseDto, "활동을 성공적으로 검색했습니다.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
import com.hobak.happinessql.domain.record.dto.RecordCreateRequestDto;
import com.hobak.happinessql.domain.record.dto.RecordCreateResponseDto;
import com.hobak.happinessql.domain.record.dto.RecordResponseDto;
import com.hobak.happinessql.domain.user.application.UserFindService;
import com.hobak.happinessql.domain.user.domain.User;
import com.hobak.happinessql.global.response.DataResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

Expand All @@ -33,15 +37,17 @@ public class RecordController {
private final RecordPagingService recordPagingService;
private final RecordCalendarListService recordCalendarListService;
private final RecordCalendarDetailService recordCalendarDetailService;
private final UserFindService userFindService;

@Operation(summary = "행복 기록 추가", description = "행복 기록을 생성합니다.")
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public DataResponseDto<RecordCreateResponseDto> createRecord(
@Valid @RequestPart(value="content") RecordCreateRequestDto requestDto,
@RequestPart(required = false) MultipartFile img,
Long userId
@AuthenticationPrincipal UserDetails userDetails
) {

User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
Long recordId = recordCreateService.createRecord(userId, requestDto, img);
RecordCreateResponseDto recordCreationResponseDto = RecordConverter.toRecordCreateResponseDto(recordId);

Expand All @@ -53,7 +59,9 @@ public DataResponseDto<RecordCreateResponseDto> createRecord(
@Parameter(name="size", description = "한 번에 가져올 레코드의 개수")
})
@GetMapping
public DataResponseDto<List<RecordResponseDto>> getRecordList(@RequestParam(required = false) Long lastRecordId, @RequestParam int size, Long userId) {
public DataResponseDto<List<RecordResponseDto>> getRecordList(@RequestParam(required = false) Long lastRecordId, @RequestParam int size, @AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
List<RecordResponseDto> responseDtos = recordPagingService.fetchRecordPagesBy(lastRecordId, size, userId);
return DataResponseDto.of(responseDtos, "행복 기록을 성공적으로 조회했습니다.");
}
Expand All @@ -63,7 +71,9 @@ public DataResponseDto<List<RecordResponseDto>> getRecordList(@RequestParam(requ
@Parameter(name="month", description = "month를 지정하지 않으면 오늘 날짜 기준으로 자동 설정됩니다.")
})
@GetMapping("/calendar")
public DataResponseDto<List<RecordCalendarResponseDto>> getRecordCalenderList(@RequestParam(required = false) Integer month, @RequestParam(required = false) Integer year, @RequestParam Long userId) {
public DataResponseDto<List<RecordCalendarResponseDto>> getRecordCalenderList(@RequestParam(required = false) Integer month, @RequestParam(required = false) Integer year, @AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
List<RecordCalendarResponseDto> responseDtos = recordCalendarListService.getHappinessAverages(month, year, userId);
return DataResponseDto.of(responseDtos, "행복 달력을 성공적으로 조회했습니다.");
}
Expand All @@ -72,7 +82,9 @@ public DataResponseDto<List<RecordCalendarResponseDto>> getRecordCalenderList(@R
parameters = {@Parameter(name="date", description = "format : yyyy-mm-dd")
})
@GetMapping("/calendar/{date}")
public DataResponseDto<List<RecordResponseDto>> getRecordCalenderList(@PathVariable String date, @RequestParam Long userId) {
public DataResponseDto<List<RecordResponseDto>> getRecordCalenderList(@PathVariable String date, @AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
Long userId = user.getUserId();
List<RecordResponseDto> responseDtos = recordCalendarDetailService.getRecords(date, userId);
return DataResponseDto.of(responseDtos, "행복 달력을 성공적으로 조회했습니다.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
Expand All @@ -23,29 +24,24 @@
@RequestMapping("api/users")
public class UserController {

private final UserFindService userFindService;
private final UserProfileService userProfileService;
private final UserService userService;
private final CustomUserDetailsService customUserDetailsService;
private final CategoryCreateService categoryCreateService;
private final UserFindService userFindService;

@NonNull
private PasswordEncoder passwordEncoder;
@GetMapping("/profile")
public DataResponseDto<Object> getUserInfo() {
// TODO : 임시값 -> 로그인한 유저의 id를 찾아내는 로직으로 변경
Long userId = 1L;

User user = userFindService.findUserById(userId);
public DataResponseDto<Object> getUserInfo(@AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
UserInfoResponseDto userInfoResponseDto = UserConverter.toUserInfoResponseDto(user);

return DataResponseDto.of(userInfoResponseDto, "유저 프로필을 성공적으로 조회했습니다.");
}

@PutMapping("/profile")
public DataResponseDto<Object> updateUserInfo(@RequestBody @Valid UserProfileUpdateRequestDto requestDto) {
Long userId = 1L;

User user = userFindService.findUserById(userId);
public DataResponseDto<Object> updateUserInfo(@RequestBody @Valid UserProfileUpdateRequestDto requestDto, @AuthenticationPrincipal UserDetails userDetails) {
User user = userFindService.findByUserDetails(userDetails);
User updatedUser = userProfileService.updateUserProfile(user, requestDto);
UserInfoResponseDto responseDto = UserConverter.toUserInfoResponseDto(updatedUser);

Expand All @@ -62,11 +58,6 @@ public DataResponseDto<JwtToken> signIn(@RequestBody SignInDto signInDto) {

}

@PostMapping("/test")
public String test(){
return "success";
}
private final CategoryCreateService categoryCreateService;
@PostMapping("/sign-up")
public DataResponseDto<Object> signUp(@RequestBody SignUpDto signUpDto){
UserDto savedUserDto = userService.signUp(signUpDto);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.hobak.happinessql.domain.user.exception.UserNotFoundException;
import com.hobak.happinessql.domain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -16,4 +17,8 @@ public User findUserById(Long userId) {
return userRespository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("User with ID" + userId));
}

public User findByUserDetails(UserDetails userDetails){
return userRespository.findUserByusername(userDetails.getUsername());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Boolean existsByUsername(String username);
User findUserByusername(String username);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.hobak.happinessql.global.auth;

import com.hobak.happinessql.domain.user.application.*;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
Expand All @@ -8,24 +9,21 @@
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;

@Slf4j
@Component
public class JwtTokenProvider {
private final Key key;
public JwtTokenProvider(@Value("${jwt.secret}")String secretKey){
private final CustomUserDetailsService customUserDetailsService;
public JwtTokenProvider(@Value("${jwt.secret}")String secretKey, CustomUserDetailsService customUserDetailsService){
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
this.key = Keys.hmacShaKeyFor(keyBytes);
this.customUserDetailsService = customUserDetailsService;
}
// Member 정보를 가지고 AccessToken, RefreshToken을 생성하는 메서드
public JwtToken generateToken(Authentication authentication) {
Expand Down Expand Up @@ -60,22 +58,9 @@ public JwtToken generateToken(Authentication authentication) {

// Jwt 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 메서드
public Authentication getAuthentication(String accessToken) {
// Jwt 토큰 복호화
Claims claims = parseClaims(accessToken);

if (claims.get("auth") == null) {
throw new RuntimeException("권한 정보가 없는 토큰입니다.");
}

// 클레임에서 권한 정보 가져오기
Collection<? extends GrantedAuthority> authorities = Arrays.stream(claims.get("auth").toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());

// UserDetails 객체를 만들어서 Authentication return
// UserDetails: interface, User: UserDetails를 구현한 class
UserDetails principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
UserDetails userDetails = customUserDetailsService.loadUserByUsername(claims.getSubject());
return new UsernamePasswordAuthenticationToken(userDetails, accessToken, userDetails.getAuthorities());
}

// 토큰 정보를 검증하는 메서드
Expand Down
Loading