Skip to content

Commit

Permalink
Merge pull request #99 from tukcomCD2024/feat#58/set-fcm
Browse files Browse the repository at this point in the history
  • Loading branch information
ggamD00 authored Jun 7, 2024
2 parents d65cfc0 + 3040607 commit 91c24dd
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
java-version: 17

- run : echo "${{ secrets.DEV_YML }}" > ./src/main/resources/application-dev.yml
- run : echo "${{ secrets.FIREBASE_KEY }}" > ./src/main/resources/firebase/firebase_key.json

- name: Log in to Docker Hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
Expand Down
2 changes: 2 additions & 0 deletions backend/memetory/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ out/
.vscode/

src/main/resources/application-*

src/main/resources/firebase/firebase_key.json
1 change: 1 addition & 0 deletions backend/memetory/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE' // Redis 라이브러리
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'com.google.firebase:firebase-admin:9.2.0' // FCM

implementation 'com.auth0:java-jwt:4.2.1'
implementation 'org.springframework.boot:spring-boot-starter-security'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class MemeController implements MemeApi {
@Override
public ResponseEntity<HttpStatus> callBackMeme(@PathVariable Long memberId,
@RequestBody ShotStackCallBackRequest shotStackCallBackRequest) {
MemeServiceDto memeServiceDto = shotStackCallBackRequest.toServiceDtoFromMemeberId(memberId);
MemeServiceDto memeServiceDto = shotStackCallBackRequest.toServiceDtoFromMemberId(memberId);

memeService.registerMeme(memeServiceDto);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,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 ShotStackCallBackRequest {

Expand All @@ -19,7 +21,7 @@ public class ShotStackCallBackRequest {
@Schema(description = "에러")
private String error;

public MemeServiceDto toServiceDtoFromMemeberId(Long memberId) {
public MemeServiceDto toServiceDtoFromMemberId(Long memberId) {
return MemeServiceDto.builder()
.memberId(memberId)
.s3Url(url)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.memetory.domain.meme.service;

import static com.example.memetory.global.firebase.FirebaseMessage.*;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -19,15 +21,19 @@
import com.example.memetory.domain.meme.exception.AccessDeniedMemeException;
import com.example.memetory.domain.meme.exception.NotFoundMemeException;
import com.example.memetory.domain.meme.repository.MemeRepository;
import com.example.memetory.global.firebase.service.FirebaseService;
import com.google.gson.Gson;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Slf4j
public class MemeService {
private final MemberService memberService;
private final MemeRepository memeRepository;
private final FirebaseService firebaseService;

@Value("${spring.ai-server.url}")
private String aiServerUrl;
Expand All @@ -39,6 +45,8 @@ public MemeResponse registerMeme(MemeServiceDto memeServiceDto) {

Meme savedMeme = memeRepository.save(meme);

firebaseService.sendMessage(MEME_CREATE_MESSAGE.toMessageWithFcmToken(member.getFcmToken()));

return MemeResponse.of(savedMeme);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.memetory.global.config;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;

@Configuration
public class FirebaseConfig {
@Value("${spring.firebase.path}")
private String firebasePath;

@Bean
public FirebaseApp initializeFirebase() {
try {
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(
GoogleCredentials.fromStream(new ClassPathResource(firebasePath).getInputStream()))
.build();
if (FirebaseApp.getApps().isEmpty()) {
return FirebaseApp.initializeApp(options);
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
return FirebaseApp.getInstance();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.memetory.global.firebase;

import java.time.LocalDateTime;

import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum FirebaseMessage {
MEME_CREATE_MESSAGE("밈 생성 완료", "밈 생성이 완료되었습니다."),
;

private String title;
private String body;

public Message toMessageWithFcmToken(String fcmToken) {
return Message.builder()
.setToken(fcmToken)
.setNotification(
Notification.builder()
.setTitle(this.getTitle())
.setBody(this.getBody())
.build()
)
.putData("time", LocalDateTime.now().toString())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.example.memetory.global.firebase.service;

import java.time.LocalDateTime;

import org.springframework.stereotype.Service;

import com.example.memetory.global.firebase.FirebaseMessage;
import com.google.firebase.FirebaseApp;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@RequiredArgsConstructor
public class FirebaseService {
private final FirebaseApp firebaseApp;

public void sendMessage(Message message) {
try {
String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
log.info("Sent message: {}", response);
} catch (FirebaseMessagingException e) {
log.error("cannot send message by token. error info : {}", e.getMessage());
}
}

private Message buildMessage(FirebaseMessage message, String fcmToken) {
return Message.builder()
.setToken(fcmToken)
.setNotification(
Notification.builder()
.setTitle(message.getTitle())
.setBody(message.getBody())
.build()
)
.putData("time", LocalDateTime.now().toString())
.build();
}
}
3 changes: 3 additions & 0 deletions backend/memetory/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ spring:
google-url: "https://www.googleapis.com/oauth2/v2/userinfo"
kakao-url: "https://kapi.kakao.com/v2/user/me"

firebase:
path: firebase/firebase_key.json


springdoc:
swagger-ui:
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static LoginRequest GOOGLE_LOGIN_REQUEST() {
}

public static LoginRequest GOOGLE_LOGIN_REQUEST_OTHER_FCM_TOKE() {
return new LoginRequest("google login token", SocialType.GOOGLE, "fcmToken");
return new LoginRequest("google login token", SocialType.GOOGLE, "fcmToken5");
}

public static String JSON_GOOGLE_OAUTH2_RESPONSE() throws JsonProcessingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public final static Member MEMBER() {
.nickname("junRain")
.socialType(SocialType.GOOGLE)
.socialId("123456789")
.fcmToken("fcmToken")
.build();
}

Expand All @@ -28,6 +29,7 @@ public final static Member OTHER_MEMBER() {
.nickname("goDDm")
.socialType(SocialType.GOOGLE)
.socialId("-2")
.fcmToken("fcmToken2")
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;

import com.example.memetory.domain.meme.dto.GenerateMemeListRequest;
import com.example.memetory.domain.meme.dto.MemePageResponse;
import com.example.memetory.domain.meme.dto.MemeResponse;
import com.example.memetory.domain.meme.dto.ShotStackCallBackRequest;
import com.example.memetory.domain.meme.entity.Meme;
import com.example.memetory.domain.meme.repository.MemeRepository;
import com.example.memetory.global.integration.BaseIntegrationTest;
Expand All @@ -26,6 +28,9 @@

@DisplayName("Meme 통합 테스트의 ")
public class MemeIntegrationTest extends BaseIntegrationTest {
@Value("${spring.firebase.token}")
private String fcmToken;

@Autowired
private MemeRepository memeRepository;

Expand Down Expand Up @@ -156,4 +161,34 @@ void Given_MemeId_When_findMemberMemePageResponse_Throw_NotFoundMemberMemeExcept
assertThat(result).isEqualTo(MEME_NOT_FOUND.getMessage());
}

@Test
@DisplayName("멤버 Id와 ShotStackCallBackRequest을 통한 밈 생성 성공")
public void Given_memberIdAndShotStackCallBackRequest_When_callBackMeme_Then_HttpStatus200() {

ShotStackCallBackRequest request = new ShotStackCallBackRequest("200", "s3Url", null);

member.updateFcmToken(fcmToken);
memberRepository.save(member);

// when
ExtractableResponse<Response> response =
given()
.log()
.all()
.auth().oauth2(accessToken)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(request)
.when()
.post("/meme/create/" + member.getId())
.then()
.log()
.all()
.extract();

Long memeCount = memeRepository.count();

// then
assertThat(memeCount).isEqualTo(1);
assertThat(200).isEqualTo(response.statusCode());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.example.memetory.domain.meme.exception.AccessDeniedMemeException;
import com.example.memetory.domain.meme.exception.NotFoundMemeException;
import com.example.memetory.domain.meme.repository.MemeRepository;
import com.example.memetory.global.firebase.service.FirebaseService;

@DisplayName("memeService 테스트의 ")
@ExtendWith(MockitoExtension.class)
Expand All @@ -42,6 +43,8 @@ public class MemeServiceTest {
private MemberService memberService;
@Mock
private MemeRepository memeRepository;
@Mock
private FirebaseService firebaseService;

private Member member;
private Meme meme;
Expand All @@ -62,6 +65,7 @@ void Given_MemesServiceDto_When_registerMeme_Then_Meme() {

given(memberService.findMemberFromId(memberId)).willReturn(member);
given(memeRepository.save(any(Meme.class))).willReturn(meme);
doNothing().when(firebaseService).sendMessage(any());

// when
MemeResponse result = memeService.registerMeme(memeServiceDto);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static com.example.memetory.domain.member.MemberFixture.*;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -42,9 +44,12 @@ public void setUp() {
databaseCleanup.afterPropertiesSet();
}

databaseCleanup.execute();

member = memberRepository.save(MEMBER());
accessToken = jwtUtil.generateAccessToken(member.getEmail());
}

@AfterEach
public void afterEach() {
databaseCleanup.execute();
}
}

0 comments on commit 91c24dd

Please sign in to comment.