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

BE/#168 유저 정보 인터셉터 구현 #172

Merged
merged 5 commits into from
Jul 17, 2023
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 @@ -2,6 +2,8 @@

import com.graphy.backend.domain.comment.dto.ReplyListDto;
import com.graphy.backend.domain.comment.service.CommentService;
import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.global.auth.jwt.annotation.CurrentUser;
import com.graphy.backend.global.result.ResultCode;
import com.graphy.backend.global.result.ResultResponse;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -26,16 +28,16 @@ public class CommentController {

@Operation(summary = "createComment", description = "댓글 생성")
@PostMapping
public ResponseEntity<ResultResponse> createComment(@Validated @RequestBody CreateCommentRequest dto) {
CreateCommentResponse response = commentService.createComment(dto);
public ResponseEntity<ResultResponse> createComment(@Validated @RequestBody CreateCommentRequest dto, @CurrentUser Member loginUser) {
CreateCommentResponse response = commentService.createComment(dto, loginUser);

return ResponseEntity.status(HttpStatus.CREATED)
.body(ResultResponse.of(ResultCode.COMMENT_CREATE_SUCCESS, response));
}

@Operation(summary = "updateComment", description = "댓글 수정")
@PutMapping("/{commentId}")
public ResponseEntity<ResultResponse> updateComment(@Validated @RequestBody UpdateCommentRequest dto, @PathVariable Long commentId) {
public ResponseEntity<ResultResponse> updateComment(@Validated @RequestBody UpdateCommentRequest dto, @PathVariable Long commentId, @CurrentUser Member loginUser) {
commentService.updateComment(commentId, dto);

return ResponseEntity.status(HttpStatus.OK)
Expand All @@ -44,7 +46,7 @@ public ResponseEntity<ResultResponse> updateComment(@Validated @RequestBody Upda

@Operation(summary = "deleteComment", description = "댓글 삭제")
@DeleteMapping("/{id}")
public ResponseEntity<ResultResponse> deleteComment(@PathVariable Long id) {
public ResponseEntity<ResultResponse> deleteComment(@PathVariable Long id, @CurrentUser Member loginUser) {
commentService.deleteComment(id);
return ResponseEntity.status(HttpStatus.OK)
.body(ResultResponse.of(ResultCode.COMMENT_DELETE_SUCCESS));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ public class CommentService {
private final CustomUserDetailsService customUserDetailsService;
private final ProjectRepository projectRepository;

public CreateCommentResponse createComment(CreateCommentRequest dto) {
public CreateCommentResponse createComment(CreateCommentRequest dto, Member loginUser) {

Project project = projectRepository.findById(dto.getProjectId())
.orElseThrow(() -> new EmptyResultException(ErrorCode.PROJECT_DELETED_OR_NOT_EXIST));
Member loginUser = customUserDetailsService.getLoginUser();

Comment parentComment = null;
if (dto.getParentId() != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.graphy.backend.domain.member.controller;

import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.member.service.MemberService;
import com.graphy.backend.global.auth.jwt.annotation.CurrentUser;
import com.graphy.backend.global.auth.jwt.dto.TokenInfo;
import com.graphy.backend.global.auth.jwt.dto.TokenDto;
import com.graphy.backend.global.result.ResultCode;
import com.graphy.backend.global.result.ResultResponse;
Expand Down Expand Up @@ -48,8 +51,8 @@ public ResponseEntity<ResultResponse> findMember(@RequestParam String nickname)

@Operation(summary = "myPage", description = "마이페이지")
@GetMapping("/myPage")
public ResponseEntity<ResultResponse> myPage() {
GetMyPageResponse result = memberService.myPage();
public ResponseEntity<ResultResponse> myPage(@CurrentUser Member member) {
GetMyPageResponse result = memberService.myPage(member);
return ResponseEntity.ok(ResultResponse.of(ResultCode.MYPAGE_GET_SUCCESS, result));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.graphy.backend.domain.member.dto;

import com.graphy.backend.domain.member.domain.Member;
import lombok.Getter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.List;

@Getter
public class MemberInfo extends User {
private Member member;
public MemberInfo(Member member) {
super(member.getEmail(), member.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_USER")));
this.member = member;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import java.sql.Ref;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -149,8 +148,8 @@ public List<GetMemberResponse> findMember(String nickname) {
.collect(Collectors.toList());
}

public GetMyPageResponse myPage() {
Member member = getLoginMember();

public GetMyPage myPage(Member member) {
List<ProjectInfo> projectInfoList = projectService.getProjectInfoList(member.getId());
return GetMyPageResponse.from(member, projectInfoList);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.graphy.backend.domain.project.controller;

import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.project.service.ProjectService;
import com.graphy.backend.global.auth.jwt.annotation.CurrentUser;
import com.graphy.backend.global.common.PageRequest;
import com.graphy.backend.global.error.ErrorCode;
import com.graphy.backend.global.error.exception.EmptyResultException;
Expand Down Expand Up @@ -30,14 +32,14 @@ public class ProjectController {

@Operation(summary = "createProject", description = "프로젝트 생성")
@PostMapping
public ResponseEntity<ResultResponse> createProject(@Validated @RequestBody CreateProjectRequest dto) {
CreateProjectResponse response = projectService.createProject(dto);
public ResponseEntity<ResultResponse> createProject(@Validated @RequestBody CreateProjectRequest dto, @CurrentUser Member loginUser) {
CreateProjectResponse response = projectService.createProject(dto, loginUser);
return ResponseEntity.ok(ResultResponse.of(ResultCode.PROJECT_CREATE_SUCCESS, response));
}

@Operation(summary = "deleteProject", description = "프로젝트 삭제(soft delete)")
@DeleteMapping("/{project_id}")
public ResponseEntity<ResultResponse> deleteProject(@PathVariable Long project_id) {
public ResponseEntity<ResultResponse> deleteProject(@PathVariable Long project_id, @CurrentUser Member loginUser) {
projectService.deleteProject(project_id);
return ResponseEntity.ok(ResultResponse.of(ResultCode.PROJECT_DELETE_SUCCESS));
}
Expand All @@ -46,7 +48,7 @@ public ResponseEntity<ResultResponse> deleteProject(@PathVariable Long project_i
@Operation(summary = "updateProject", description = "프로젝트 수정(변경감지)")
@PutMapping("/{projectId}")
public ResponseEntity<ResultResponse> updateProject(@PathVariable Long projectId,
@RequestBody @Validated UpdateProjectRequest dto) {
@RequestBody @Validated UpdateProjectRequest dto, @CurrentUser Member loginUser) {
UpdateProjectResponse result = projectService.updateProject(projectId, dto);
return ResponseEntity.ok(ResultResponse.of(ResultCode.PROJECT_UPDATE_SUCCESS, result));
}
Expand Down Expand Up @@ -75,7 +77,7 @@ public ResponseEntity<ResultResponse> getProject(@PathVariable Long projectId) {

@Operation(summary = "getProjectPlan", description = "프로젝트 고도화 계획 제안")
@PostMapping("/plans")
public ResponseEntity<ResultResponse> createPlan(final @RequestBody GetPlanRequest getPlanRequest) throws ExecutionException, InterruptedException {
public ResponseEntity<ResultResponse> createPlan(final @RequestBody GetPlanRequest getPlanRequest, @CurrentUser Member loginUser) throws ExecutionException, InterruptedException {
String prompt = projectService.getPrompt(getPlanRequest);
projectService.checkGptRequestToken(prompt);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ public class ProjectService {
// br.close();
// }

public CreateProjectResponse createProject(CreateProjectRequest dto) {
Member loginUser = customUserDetailsService.getLoginUser();
public CreateProjectResponse createProject(CreateProjectRequest dto, Member loginUser) {
Project entity = mapper.toEntity(dto,loginUser);
if (dto.getTechTags() != null) {
Tags foundTags = getTagsWithName(dto.getTechTags());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
package com.graphy.backend.global.auth.jwt;

import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.member.dto.MemberInfo;
import com.graphy.backend.domain.member.repository.MemberRepository;
import com.graphy.backend.global.error.ErrorCode;
import com.graphy.backend.global.error.exception.EmptyResultException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {

private final MemberRepository memberRepository;

@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return memberRepository.findByEmail(email)
Expand All @@ -31,15 +26,10 @@ public UserDetails loadUserByUsername(String email) throws UsernameNotFoundExcep
}

private UserDetails createUserDetails(Member member) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(member.getRole().name());
return new User(
member.getEmail(),
member.getPassword(),
Collections.singleton(grantedAuthority)
);
return new MemberInfo(member);
}

public Member getLoginUser(){
public Member getLoginUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String email = ((UserDetails) principal).getUsername();
return memberRepository.findByEmail(email).orElseThrow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
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;

Expand All @@ -31,7 +30,9 @@ public class TokenProvider {
private final Key key;


public TokenProvider(@Value("${jwt.secret}") String secretKey) {
private final CustomUserDetailsService customUserDetailsService;
public TokenProvider(@Value("${jwt.secret}") String secretKey, CustomUserDetailsService customUserDetailsService) {
this.customUserDetailsService = customUserDetailsService;
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
this.key = Keys.hmacShaKeyFor(keyBytes);
}
Expand Down Expand Up @@ -83,9 +84,9 @@ public Authentication getAuthentication(String accessToken) {
.collect(Collectors.toList());

// UserDetails 객체를 만들어서 Authentication 리턴
UserDetails principal = new User(claims.getSubject(), "", authorities);
UserDetails principal = customUserDetailsService.loadUserByUsername(claims.getSubject());

return new UsernamePasswordAuthenticationToken(principal, "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", principal.getAuthorities());
}

public boolean validateToken(String token) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.graphy.backend.global.auth.jwt.annotation;

import org.springframework.security.core.annotation.AuthenticationPrincipal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member")
public @interface CurrentUser {
}
Loading