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

Fix : DIG-177 FCM 웹 푸시 버그 수정 #103

Merged
merged 1 commit into from
Nov 27, 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
@@ -0,0 +1,39 @@
package com.ogjg.daitgym.alarm.controller.fcm;

import com.ogjg.daitgym.alarm.dto.FcmTokenRequestDto;
import com.ogjg.daitgym.alarm.service.FcmTokenService;
import com.ogjg.daitgym.common.exception.ErrorCode;
import com.ogjg.daitgym.common.response.ApiResponse;
import com.ogjg.daitgym.config.security.details.OAuth2JwtUserDetails;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/notification")
public class FcmTokenController {

private final FcmTokenService fcmTokenService;


@GetMapping("/token")
public ApiResponse<Boolean> getNotification(@AuthenticationPrincipal OAuth2JwtUserDetails oAuth2JwtUserDetails) {

return new ApiResponse<>(ErrorCode.SUCCESS, fcmTokenService.getNotification(oAuth2JwtUserDetails));
}

@PostMapping("/token")
public ApiResponse<Void> saveNotification(@RequestBody FcmTokenRequestDto fcmTokenRequestDto,
@AuthenticationPrincipal OAuth2JwtUserDetails oAuth2JwtUserDetails) {
fcmTokenService.saveNotification(fcmTokenRequestDto, oAuth2JwtUserDetails);
return new ApiResponse<>(ErrorCode.SUCCESS);
}

@PatchMapping("/token")
public ApiResponse<Void> updateNotification(@RequestBody FcmTokenRequestDto fcmTokenRequestDto,
@AuthenticationPrincipal OAuth2JwtUserDetails oAuth2JwtUserDetails) {
fcmTokenService.updateNotification(fcmTokenRequestDto, oAuth2JwtUserDetails);
return new ApiResponse<>(ErrorCode.SUCCESS);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ public interface FcmTokenRepository extends JpaRepository<FcmToken, Long> {
boolean existsByUserAndToken(User user, String token);

Optional<FcmToken> findByUserAndToken(User user, String token);

Optional<FcmToken> findByUser(User user);

Optional<FcmToken> findByUserEmail(String email);
}

42 changes: 0 additions & 42 deletions src/main/java/com/ogjg/daitgym/alarm/service/FcmAlarmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,14 @@
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.WebpushConfig;
import com.google.firebase.messaging.WebpushNotification;
import com.ogjg.daitgym.alarm.dto.FcmTokenRequestDto;
import com.ogjg.daitgym.alarm.dto.NotificationRequestDto;
import com.ogjg.daitgym.alarm.repository.FcmTokenRepository;
import com.ogjg.daitgym.common.exception.exercise.NotFoundExercise;
import com.ogjg.daitgym.common.exception.fcmtoken.NotFoundFcmToken;
import com.ogjg.daitgym.common.exception.journal.NotFoundExerciseList;
import com.ogjg.daitgym.config.security.details.OAuth2JwtUserDetails;
import com.ogjg.daitgym.domain.FcmToken;
import com.ogjg.daitgym.domain.User;
import com.ogjg.daitgym.domain.exercise.Exercise;
import com.ogjg.daitgym.domain.journal.ExerciseJournal;
import com.ogjg.daitgym.domain.journal.ExerciseList;
import com.ogjg.daitgym.exercise.repository.ExerciseRepository;
import com.ogjg.daitgym.journal.repository.exerciselist.ExerciseListRepository;
import com.ogjg.daitgym.user.service.UserHelper;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand All @@ -33,32 +25,8 @@
@RequiredArgsConstructor
public class FcmAlarmService {

private final UserHelper userHelper;
private final ExerciseRepository exerciseRepository;
private final FcmTokenRepository notificationRepository;
private final ExerciseListRepository exerciseListRepository;
private final FcmTokenRepository fcmTokenRepository;


/**
* FCM 토큰값 저장
*/
@Transactional
public void saveNotification(FcmTokenRequestDto fcmTokenRequestDto, OAuth2JwtUserDetails oAuth2JwtUserDetails) {
User user = userHelper.findUserByEmail(oAuth2JwtUserDetails.getEmail());

String token = fcmTokenRequestDto.getToken();

if (!fcmTokenRepository.existsByUserAndToken(user, token)) {
FcmToken notification = FcmToken.builder()
.token(token)
.user(user)
.build();
notificationRepository.save(notification);
} else {
log.info("이미 토큰이 존재합니다.");
}
}


public String alarmMessage(ExerciseJournal exerciseJournal) {
Expand Down Expand Up @@ -102,14 +70,4 @@ public void sendNotification(NotificationRequestDto requestDto) throws Execution
String response = FirebaseMessaging.getInstance().sendAsync(message).get();
log.info("Send message : " + response);
}


public void deleteFcmToken(OAuth2JwtUserDetails oAuth2JwtUserDetails, FcmTokenRequestDto fcmTokenRequestDto) {
User user = userHelper.findUserByEmail(oAuth2JwtUserDetails.getEmail());
String token = fcmTokenRequestDto.getToken();

FcmToken fcmToken = fcmTokenRepository.findByUserAndToken(user, token).orElseThrow(NotFoundFcmToken::new);
fcmTokenRepository.delete(fcmToken);
}

}
71 changes: 71 additions & 0 deletions src/main/java/com/ogjg/daitgym/alarm/service/FcmTokenService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.ogjg.daitgym.alarm.service;

import com.ogjg.daitgym.alarm.dto.FcmTokenRequestDto;
import com.ogjg.daitgym.alarm.repository.FcmTokenRepository;
import com.ogjg.daitgym.common.exception.fcmtoken.NotFoundFcmToken;
import com.ogjg.daitgym.common.exception.user.NotFoundUser;
import com.ogjg.daitgym.config.security.details.OAuth2JwtUserDetails;
import com.ogjg.daitgym.domain.FcmToken;
import com.ogjg.daitgym.domain.User;
import com.ogjg.daitgym.user.service.UserHelper;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class FcmTokenService {

private final UserHelper userHelper;
private final FcmTokenRepository notificationRepository;
private final FcmTokenRepository fcmTokenRepository;


public boolean getNotification(OAuth2JwtUserDetails oAuth2JwtUserDetails) {

return fcmTokenRepository.findByUserEmail(oAuth2JwtUserDetails.getEmail()).isPresent();
}

@Transactional
public void updateNotification(FcmTokenRequestDto fcmTokenRequestDto, OAuth2JwtUserDetails oAuth2JwtUserDetails) {
User user = userHelper.findUserByEmail(oAuth2JwtUserDetails.getEmail());
String token = fcmTokenRequestDto.getToken();

FcmToken fcmToken = fcmTokenRepository.findByUser(user).orElseThrow(NotFoundUser::new);
fcmToken.update(token);
fcmTokenRepository.save(fcmToken);
}

@Transactional
public void saveNotification(FcmTokenRequestDto fcmTokenRequestDto, OAuth2JwtUserDetails oAuth2JwtUserDetails) {

try {
User user = userHelper.findUserByEmail(oAuth2JwtUserDetails.getEmail());
String token = fcmTokenRequestDto.getToken();

if (!fcmTokenRepository.existsByUserAndToken(user, token)) {
FcmToken notification = FcmToken.builder()
.token(token)
.user(user)
.build();
notificationRepository.save(notification);
log.info("토큰 저장 성공");
} else {
log.info("이미 토큰이 존재합니다.");
}
} catch (Exception e) {
log.error("트랜잭션 롤백 발생", e);
throw e;
}
}

public void deleteFcmToken(FcmTokenRequestDto fcmTokenRequestDto, OAuth2JwtUserDetails oAuth2JwtUserDetails) {
User user = userHelper.findUserByEmail(oAuth2JwtUserDetails.getEmail());
String token = fcmTokenRequestDto.getToken();

FcmToken fcmToken = fcmTokenRepository.findByUserAndToken(user, token).orElseThrow(NotFoundFcmToken::new);
fcmTokenRepository.delete(fcmToken);
}
}
36 changes: 24 additions & 12 deletions src/main/java/com/ogjg/daitgym/alarm/service/ScheduledService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.ogjg.daitgym.alarm.dto.NotificationRequestDto;
import com.ogjg.daitgym.alarm.repository.FcmTokenRepository;
import com.ogjg.daitgym.comment.feedExerciseJournal.exception.NotFoundExerciseJournal;
import com.ogjg.daitgym.domain.FcmToken;
import com.ogjg.daitgym.domain.User;
import com.ogjg.daitgym.domain.journal.ExerciseJournal;
Expand All @@ -14,6 +13,7 @@

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

@Slf4j
Expand All @@ -27,31 +27,43 @@ public class ScheduledService {


/**
* 7시 30분에 알림 메세지 보내기
* 8시에 알림 메세지 보내기
*/
@Scheduled(cron = "*/10 * * * * *")
@Scheduled(cron = "0 0 8 * * *")
public void scheduledSend() throws ExecutionException, InterruptedException {

List<FcmToken> fcmTokens = fcmTokenRepository.findAll();

if (fcmTokens.isEmpty()) {
log.info("fcmToken이 없어, 작업을 하지 않습니다.");
log.info("FCM 토큰이 비어있어, 알림전송 실패");
return;
}

for (FcmToken fcmToken : fcmTokens) {
User user = fcmToken.getUser();
ExerciseJournal exerciseJournal = exerciseJournalRepository.findByUserAndJournalDate(user, LocalDate.now()).orElseThrow(NotFoundExerciseJournal::new);
Optional<ExerciseJournal> optionalExerciseJournal = exerciseJournalRepository.findByUserAndJournalDate(user, LocalDate.now());

String message = notificationService.alarmMessage(exerciseJournal);
if (optionalExerciseJournal.isPresent()) {
ExerciseJournal exerciseJournal = optionalExerciseJournal.get();
String message = notificationService.alarmMessage(exerciseJournal);

NotificationRequestDto notificationRequestDto = NotificationRequestDto.builder()
.title("[DaItGym 운동 알림]")
.message(message)
.token(fcmToken.getToken())
.build();
NotificationRequestDto notificationRequestDto = NotificationRequestDto.builder()
.title("[DaItGym 운동 알림]")
.message(message)
.token(fcmToken.getToken())
.build();

notificationService.sendNotification(notificationRequestDto);
notificationService.sendNotification(notificationRequestDto);

} else {
NotificationRequestDto notificationRequestDto = NotificationRequestDto.builder()
.title("[DaItGym 운동 알림]")
.message("오늘 운동일지가 비어있어요!")
.token(fcmToken.getToken())
.build();

notificationService.sendNotification(notificationRequestDto);
}
}
log.info("웹푸시 보냈어!");
}
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/ogjg/daitgym/domain/FcmToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class FcmToken {
@Column(name = "notification_id")
private Long id;

@OneToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "email")
private User user;

Expand All @@ -30,4 +30,8 @@ public FcmToken(String token, User user) {
this.user = user;
}

public void update(String token) {
this.token = token;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ogjg.daitgym.alarm.dto.FcmTokenRequestDto;
import com.ogjg.daitgym.alarm.service.FcmAlarmService;
import com.ogjg.daitgym.alarm.service.FcmTokenService;
import com.ogjg.daitgym.common.exception.ErrorCode;
import com.ogjg.daitgym.common.response.ApiResponse;
import com.ogjg.daitgym.config.security.details.OAuth2JwtUserDetails;
Expand All @@ -29,7 +29,7 @@
public class UserController {

private final UserService userService;
private final FcmAlarmService fcmAlarmService;
private final FcmTokenService fcmTokenService;

private final ObjectMapper objectMapper;

Expand All @@ -38,10 +38,10 @@ public class UserController {
*/
@PostMapping("/logout")
public ApiResponse<?> logout(HttpServletResponse response,
@AuthenticationPrincipal OAuth2JwtUserDetails oAuth2JwtUserDetails,
@RequestBody FcmTokenRequestDto fcmTokenRequestDto) {
@RequestBody FcmTokenRequestDto fcmTokenRequestDto,
@AuthenticationPrincipal OAuth2JwtUserDetails oAuth2JwtUserDetails) {
response.setHeader("Set-Cookie", userService.getExpiredResponseCookie().toString());
fcmAlarmService.deleteFcmToken(oAuth2JwtUserDetails, fcmTokenRequestDto);
fcmTokenService.deleteFcmToken(fcmTokenRequestDto, oAuth2JwtUserDetails);
return new ApiResponse<>(ErrorCode.SUCCESS.changeMessage("로그아웃 성공"));
}

Expand Down