Skip to content

Commit

Permalink
Merge pull request #97 from tukcomCD2024/feat#94/integration-testing
Browse files Browse the repository at this point in the history
Feat#94/integration testing
  • Loading branch information
ggamD00 authored Jun 4, 2024
2 parents acf4cd8 + 72bcdb6 commit 2ac75b1
Show file tree
Hide file tree
Showing 29 changed files with 770 additions and 176 deletions.
6 changes: 5 additions & 1 deletion backend/memetory/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ dependencies {
// Swagger 적용
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'


// AWS SDK
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

Expand All @@ -59,6 +58,11 @@ dependencies {
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.security:spring-security-test'

// rest-assured
testImplementation 'io.rest-assured:rest-assured:5.1.1'

// Mock Wire
testImplementation "org.wiremock:wiremock-jetty12:3.6.0"
}

clean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor()
@Schema(description = "로그인 포맷")
public class LoginRequest {
@Schema(description = "인증서버에서 받아온 access token을 입력")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package com.example.memetory.domain.auth.service;

import static com.example.memetory.domain.member.entity.SocialType.*;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
Expand All @@ -23,7 +19,10 @@
@RequiredArgsConstructor
public class OAuth2ProviderService {

private static final Logger log = LoggerFactory.getLogger(OAuth2ProviderService.class);
@Value("${spring.oauth2.google-url}")
private String googleUrl;
@Value("${spring.oauth2.kakao-url}")
private String kakaoUrl;

public OAuth2UserInfo getUserInfo(LoginRequest request) {
return switch (request.getSocialType()) {
Expand All @@ -33,7 +32,7 @@ public OAuth2UserInfo getUserInfo(LoginRequest request) {
}

private OAuth2UserInfo getKakaoUserInfo(LoginRequest request) {
Map attributes = WebClient.create(KAKAO.getProviderUrl())
Map attributes = WebClient.create(kakaoUrl)
.get()
.headers(httpHeaders -> {
httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
Expand All @@ -49,7 +48,7 @@ private OAuth2UserInfo getKakaoUserInfo(LoginRequest request) {
}

private OAuth2UserInfo getGoogleUserInfo(LoginRequest request) {
Map attributes = WebClient.create(GOOGLE.getProviderUrl())
Map attributes = WebClient.create(googleUrl)
.get()
.headers(httpHeaders -> {
httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

import java.util.Map;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GoogleOAuth2UserInfo extends OAuth2UserInfo {

public GoogleOAuth2UserInfo(Map<String, Object> attributes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
@RequiredArgsConstructor
@Getter
public enum SocialType {
GOOGLE("https://www.googleapis.com/oauth2/v2/userinfo"),
KAKAO("https://kapi.kakao.com/v2/user/me");

private final String providerUrl;
GOOGLE(),
KAKAO();

@JsonCreator
public static SocialType from(String s) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@

import static com.example.memetory.global.response.ResultCode.*;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import com.example.memetory.domain.meme.dto.GenerateMemeListRequest;
import com.example.memetory.domain.meme.dto.MemePageResponse;
Expand All @@ -33,9 +29,6 @@
public class MemeController implements MemeApi {
private final MemeService memeService;

@Value("${spring.ai-server.url}")
private String AI_SERVER_URL;

@PostMapping("/create/{memberId}")
@Override
public ResponseEntity<HttpStatus> callBackMeme(@PathVariable Long memberId,
Expand All @@ -53,22 +46,15 @@ public ResponseEntity<ResultResponse> registerMeme(@LoginMemberEmail String emai
@RequestBody GenerateMemeListRequest generateMemeListRequest) {

MemeServiceDto memeServiceDto = generateMemeListRequest.toServiceDto(email);
String aiServerSendJson = memeService.getAIServerSendJson(memeServiceDto);

WebClient.create(AI_SERVER_URL)
.post()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(aiServerSendJson))
.retrieve()
.bodyToMono(Void.class)
.subscribe();
memeService.sendToMemeServer(memeServiceDto);

return ResponseEntity.status(HttpStatus.CREATED).body(ResultResponse.of(CREATE_MEME_SUCCESS));
}

@GetMapping("/{memeId}")
@Override
public ResponseEntity<ResultResponse> findMemberMemeResponse(@LoginMemberEmail String email, @PathVariable Long memeId) {
public ResponseEntity<ResultResponse> findMemberMemeResponse(@LoginMemberEmail String email,
@PathVariable Long memeId) {
MemeServiceDto memeServiceDto = MemeServiceDto.fromEmailAndMemeId(email, memeId);
MemeResponse response = memeService.findMemberMemeResponse(memeServiceDto);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import com.google.gson.annotations.SerializedName;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AIServerSendDto {
@SerializedName("member_id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,28 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor()
@Schema(description = "밈 생성 포맷")
public class GenerateMemeDto {
@Schema(description = "적용하고 싶은 이미지")
@SerializedName("source_image")
private String sourceImage;
@Schema(description = "적용하고 싶은 이미지")
@SerializedName("source_image")
private String sourceImage;

@Schema(description = "배경 이미지")
@SerializedName("target_image")
private String targetImage;
@Schema(description = "배경 이미지")
@SerializedName("target_image")
private String targetImage;

@Schema(description = "대사")
@SerializedName("text")
private String text;
@Schema(description = "일레븐랩스 목소리 ID")
@SerializedName("voice_id")
private String voiceId;
@Schema(description = "대사")
@SerializedName("text")
private String text;

@Schema(description = "일레븐랩스 목소리 ID")
@SerializedName("voice_id")
private String voiceId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor
@Schema(description = "밈 생성 리스트 포맷")
public class GenerateMemeListRequest {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.example.memetory.domain.meme.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import com.example.memetory.domain.member.entity.Member;
import com.example.memetory.domain.member.service.MemberService;
Expand All @@ -25,6 +29,9 @@ public class MemeService {
private final MemberService memberService;
private final MemeRepository memeRepository;

@Value("${spring.ai-server.url}")
private String aiServerUrl;

@Transactional
public MemeResponse registerMeme(MemeServiceDto memeServiceDto) {
Member member = memberService.findMemberFromId(memeServiceDto.getMemberId());
Expand All @@ -36,7 +43,17 @@ public MemeResponse registerMeme(MemeServiceDto memeServiceDto) {
}

@Transactional(readOnly = true)
public String getAIServerSendJson(MemeServiceDto memeServiceDto) {
public void sendToMemeServer(MemeServiceDto memeServiceDto) {
WebClient.create(aiServerUrl)
.post()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(convertMemeServiceDtoIntoJson(memeServiceDto)))
.retrieve()
.bodyToMono(Void.class)
.subscribe();
}

private String convertMemeServiceDtoIntoJson(MemeServiceDto memeServiceDto) {
Gson gson = new Gson();

Member member = memberService.findMemberFromEmail(memeServiceDto.getEmail());
Expand All @@ -53,7 +70,7 @@ public String getAIServerSendJson(MemeServiceDto memeServiceDto) {
public MemeResponse findMemberMemeResponse(MemeServiceDto memeServiceDto) {
Meme meme = memeRepository.findById(memeServiceDto.getMemeId()).orElseThrow(NotFoundMemeException::new);

Member loginMember = memberService.findMemberFromId(memeServiceDto.getMemberId());
Member loginMember = memberService.findMemberFromEmail(memeServiceDto.getEmail());
Member memeMember = meme.getMember();
certifyMemeMember(memeMember, loginMember);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.memetory.global.security.jwt.filter;

import static jakarta.servlet.http.HttpServletResponse.*;

import java.io.IOException;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Expand All @@ -13,7 +15,7 @@

import com.example.memetory.domain.member.entity.Member;
import com.example.memetory.domain.member.repository.MemberRepository;
import com.example.memetory.global.security.jwt.exception.InvalidTokenException;
import com.example.memetory.global.security.jwt.exception.NotFoundTokenException;
import com.example.memetory.global.security.jwt.refresh.domain.RefreshToken;
import com.example.memetory.global.security.jwt.refresh.service.RefreshTokenService;
import com.example.memetory.global.security.jwt.service.JwtService;
Expand All @@ -24,10 +26,8 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationProcessingFilter extends OncePerRequestFilter {

private static final String NO_CHECK_URL = "/login";
Expand All @@ -41,49 +41,41 @@ public class JwtAuthenticationProcessingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {

if (request.getRequestURI().equals(NO_CHECK_URL)) {
filterChain.doFilter(request, response);
return;
}

String refreshToken = jwtService.extractRefreshToken(request).orElse(null);

if (refreshToken != null) {
try {
String refreshToken = jwtService.extractRefreshToken(request);
checkRefreshTokenAndReIssueAccessToken(response, refreshToken);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}

if (refreshToken == null) {
sendError(response, HttpServletResponse.SC_UNAUTHORIZED);
} catch (NotFoundTokenException e) {
checkAccessTokenAndAuthentication(request, response, filterChain);
}
}

public void checkRefreshTokenAndReIssueAccessToken(HttpServletResponse response, String refreshToken) {
private void checkRefreshTokenAndReIssueAccessToken(HttpServletResponse response, String refreshToken) {
if (jwtService.isTokenValid(refreshToken)) {
RefreshToken refresh = refreshTokenService.findByToken(refreshToken);
jwtService.sendAccessAndRefreshToken(response, refresh.getEmail());
}
}

public void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
log.info("checkAccessTokenAndAuthentication() 호출");
private void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
try {
jwtService.extractAccessToken(request)
.ifPresent(accessToken -> jwtService.extractEmail(accessToken)
.ifPresentOrElse(email -> memberRepository.findByEmail(email).ifPresent(this::saveAuthentication),
() -> {
throw new InvalidTokenException();
}
)
);
String email = jwtService.getEmail(request);
memberRepository.findByEmail(email).ifPresent(this::saveAuthentication);
filterChain.doFilter(request, response);
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
sendError(response, SC_FORBIDDEN);
}
filterChain.doFilter(request, response);
}

public void saveAuthentication(Member myMember) {
private void saveAuthentication(Member myMember) {
String password = PasswordUtil.generateRandomPassword();

UserDetails userDetailsUser = User.builder()
Expand All @@ -97,4 +89,12 @@ public void saveAuthentication(Member myMember) {

SecurityContextHolder.getContext().setAuthentication(authentication);
}

private void sendError(HttpServletResponse response, int errorCode) {
try {
response.sendError(errorCode);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit 2ac75b1

Please sign in to comment.