Skip to content

Commit

Permalink
feat: 프로젝트 관련 API 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
minje0204 committed Oct 8, 2024
1 parent 8a13275 commit a159872
Show file tree
Hide file tree
Showing 28 changed files with 580 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com._119.wepro.global.handler.CustomLogoutHandler;
import com._119.wepro.global.handler.CustomLogoutSuccessHandler;
import com._119.wepro.global.security.CustomOidcAuthenticationSuccessHandler;
import com._119.wepro.global.security.CustomOidcUserService;
import com._119.wepro.global.security.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
Expand All @@ -25,6 +26,7 @@
public class WebSecurityConfig {

private final JwtTokenProvider jwtTokenProvider;
private final CustomOidcUserService customOidcUserService;
private final CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

@Bean
Expand Down Expand Up @@ -55,6 +57,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.httpBasic(withDefaults())
.oauth2Login(oauth2Login -> oauth2Login
.userInfoEndpoint(userInfo -> userInfo.oidcUserService(customOidcUserService))
.failureHandler(customAuthenticationFailureHandler)
.successHandler(customOidcAuthenticationSuccessHandler())
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public enum ProjectErrorCode implements ErrorCode {

PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, "Project not found"),
PROJECT_MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "등록하시려고 하는 멤버가 존재하지 않습니다."),
;

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import java.io.IOException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

Expand All @@ -22,18 +24,24 @@ public class CustomOidcAuthenticationSuccessHandler extends SimpleUrlAuthenticat

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
Authentication authentication) throws IOException, ServletException {
log.info("authentication success");

CustomOidcUser user = (CustomOidcUser) authentication.getPrincipal();
CustomOidcUser customOidcUser = (CustomOidcUser) authentication.getPrincipal();

// 토큰 발급
TokenInfo tokenInfo = jwtTokenProvider.generateToken(user.getAttribute("sub"),
user.getMemberRole());
// JWT 토큰 발급
TokenInfo tokenInfo = jwtTokenProvider.generateToken(String.valueOf(customOidcUser.getMemberId()),
customOidcUser.getMemberRole());

// SecurityContext에 명시적으로 CustomOidcUser 저장 (이미 존재하지만, 명확히 보장하기 위함)
Authentication newAuth = new UsernamePasswordAuthenticationToken(customOidcUser,
authentication.getCredentials(), authentication.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);

// 리다이렉트
response.sendRedirect(
"http://localhost:8081/oauth2/authorization/login?token=" + tokenInfo.getAccessToken()
+ "&refresh=" + tokenInfo.getRefreshToken() + "&isGuest=" + (user.isGuest() ? "true"
: "false"));
+ "&refresh=" + tokenInfo.getRefreshToken() + "&isGuest=" + (customOidcUser.isGuest()
? "true" : "false"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import com._119.wepro.member.domain.Provider;
import com._119.wepro.member.domain.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Slf4j
public class CustomOidcUserService extends OidcUserService {

private final MemberRepository memberRepository;
Expand All @@ -21,6 +23,7 @@ public class CustomOidcUserService extends OidcUserService {
public OidcUser loadUser(OidcUserRequest userRequest) {

OidcUser oidcUser = super.loadUser(userRequest);

Member newMember = fetchOrCreate(oidcUser);

return new CustomOidcUser(oidcUser, newMember.getId(), newMember.getRole());
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/_119/wepro/image/domain/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@

import static lombok.AccessLevel.PROTECTED;

import com._119.wepro.image.dto.request.ImageCreateRequest;
import com._119.wepro.project.domain.Project;
import com._119.wepro.project.dto.request.ProjectRequest.ProjectCreateRequest;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand All @@ -11,7 +22,23 @@
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = PROTECTED)
@Entity
@Builder
public class Image {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String url;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "project_id")
private Project project;

public static Image of(ImageCreateRequest imageCreateRequest) {
return Image.builder()
.url(imageCreateRequest.getUrl())
.project(imageCreateRequest.getProject())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com._119.wepro.image.dto.request;

import com._119.wepro.project.domain.Project;
import lombok.Data;

@Data
public class ImageCreateRequest {
String url;
Project project;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com._119.wepro.image.dto;
package com._119.wepro.image.dto.response;

import com._119.wepro.image.domain.Image;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com._119.wepro.image.presentation;

import com._119.wepro.image.dto.ImagesResponse;
import com._119.wepro.image.dto.response.ImagesResponse;
import com._119.wepro.image.service.ImageService;
import java.net.URI;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com._119.wepro.global.exception.RestApiException;
import com._119.wepro.image.domain.ImageFile;
import com._119.wepro.image.domain.S3ImageEvent;
import com._119.wepro.image.dto.ImagesResponse;
import com._119.wepro.image.dto.response.ImagesResponse;
import com._119.wepro.image.infrastructure.ImageUploader;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/_119/wepro/member/domain/Member.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com._119.wepro.member.domain;

import com._119.wepro.global.BaseEntity;
import com._119.wepro.project.domain.ProjectMember;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
Expand All @@ -10,14 +11,17 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.OneToMany;
import jakarta.persistence.PostPersist;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import java.util.Set;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
Expand All @@ -29,6 +33,7 @@
@Index(name = "idx_provider_id", columnList = "providerId")
}
)
@Setter
public class Member extends BaseEntity {

@Id
Expand All @@ -55,6 +60,9 @@ public class Member extends BaseEntity {

private LocalDateTime inactivatedAt;

@OneToMany(mappedBy = "member")
private Set<ProjectMember> projectMembers;

// 엔티티가 저장된 후 id로 태그를 생성합니다.
//todo 태그 저장안되는 이슈 확인하기
@PostPersist
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com._119.wepro.member.domain.repository;

import static com._119.wepro.member.domain.QMember.member;

import com._119.wepro.member.domain.Member;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@RequiredArgsConstructor
@Repository
public class MemberCustomRepository {

private final JPAQueryFactory queryFactory;

public List<Member> findMembers(String keyword) {
return queryFactory.select(member).from(member)
.where(member.tag.contains(keyword).or(member.profile.name.contains(keyword))).fetch();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com._119.wepro.member.dto.response;

import com._119.wepro.member.domain.Member;
import java.io.Serializable;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class MemberListResponse implements Serializable {

private Long id;
private String name;
private String tag;

public static MemberListResponse of(Member member){
return MemberListResponse.builder()
.id(member.getId())
.name(member.getProfile().getName())
.tag(member.getTag())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com._119.wepro.member.presentation;

import static com._119.wepro.global.security.constant.SecurityConstants.ACCESS_TOKEN_HEADER;
import static com._119.wepro.global.security.constant.SecurityConstants.REFRESH_TOKEN_HEADER;

import com._119.wepro.global.util.SecurityUtil;
import com._119.wepro.member.dto.response.MemberListResponse;
import com._119.wepro.member.service.MemberService;
import com._119.wepro.member.service.ReissueService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
Expand All @@ -12,15 +11,17 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping("members")
@RequiredArgsConstructor
public class MemberController {

private final MemberService memberService;
private final SecurityUtil securityUtil;
private final ReissueService reissueService;

Expand All @@ -35,4 +36,10 @@ public ResponseEntity<Void> refresh(HttpServletRequest request, HttpServletRespo
reissueService.reissue(request, response);
return ResponseEntity.ok().build();
}

@GetMapping()
public ResponseEntity<List<MemberListResponse>> findMembers(@RequestParam("key") String keyword) {
List<MemberListResponse> result = memberService.findMembers(keyword);
return ResponseEntity.ok(result);
}
}
15 changes: 14 additions & 1 deletion src/main/java/com/_119/wepro/member/service/MemberService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
package com._119.wepro.member.service;

import com._119.wepro.member.domain.Member;
import com._119.wepro.member.domain.repository.MemberCustomRepository;
import com._119.wepro.member.dto.response.MemberListResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MemberService {

}
private final MemberCustomRepository memberCustomRepository;

@Cacheable(value = "findMemberCache")
public List<MemberListResponse> findMembers(String keyword) {
List<Member> result = memberCustomRepository.findMembers(keyword);

return result.stream().map(MemberListResponse::of).toList();
}
}
Loading

0 comments on commit a159872

Please sign in to comment.