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] fcm token 중복 검증 추가 #223

Merged
merged 5 commits into from
Feb 16, 2024
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
@@ -1,6 +1,7 @@
package codesquad.fineants.domain.fcm_token;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
Expand All @@ -11,6 +12,9 @@ public interface FcmRepository extends JpaRepository<FcmToken, Long> {
@Query("select f from FcmToken f where f.member.id = :memberId")
List<FcmToken> findAllByMemberId(@Param("memberId") Long memberId);

@Query("select f from FcmToken f where f.token = :token and f.member.id = :memberId")
Optional<FcmToken> findByToken(@Param("token") String token, @Param("memberId") Long memberId);

@Modifying
@Query("delete from FcmToken f where f.token in (:tokens)")
int deleteAllByTokens(@Param("tokens") List<String> tokens);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
@RequiredArgsConstructor
public enum FcmErrorCode implements ErrorCode {

BAD_REQUEST_FCM_TOKEN(HttpStatus.BAD_REQUEST, "유효하지 않은 FCM 토큰입니다");
BAD_REQUEST_FCM_TOKEN(HttpStatus.BAD_REQUEST, "유효하지 않은 FCM 토큰입니다"),
CONFLICT_FCM_TOKEN(HttpStatus.CONFLICT, "중복된 FCM 토큰입니다");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import codesquad.fineants.spring.api.errors.errorcode.FcmErrorCode;
import codesquad.fineants.spring.api.errors.errorcode.MemberErrorCode;
import codesquad.fineants.spring.api.errors.exception.BadRequestException;
import codesquad.fineants.spring.api.errors.exception.ConflictException;
import codesquad.fineants.spring.api.errors.exception.NotFoundResourceException;
import codesquad.fineants.spring.api.fcm.request.FcmRegisterRequest;
import codesquad.fineants.spring.api.fcm.response.FcmDeleteResponse;
Expand All @@ -36,6 +37,7 @@ public class FcmService {
@Transactional
public FcmRegisterResponse registerToken(FcmRegisterRequest request, AuthMember authMember) {
Member member = findMember(authMember);
verifyUniqueFcmToken(request.getFcmToken(), authMember.getMemberId());
verifyFcmToken(request.getFcmToken());
FcmToken saveFcmToken = fcmRepository.save(request.toEntity(member));
return FcmRegisterResponse.from(saveFcmToken);
Expand All @@ -51,6 +53,7 @@ private void verifyFcmToken(String token) {
firebaseMessaging.send(message, true);
} catch (FirebaseMessagingException e) {
log.info(e.getMessage(), e);

throw new BadRequestException(FcmErrorCode.BAD_REQUEST_FCM_TOKEN);
}
}
Expand All @@ -60,6 +63,12 @@ private Member findMember(AuthMember authMember) {
.orElseThrow(() -> new NotFoundResourceException(MemberErrorCode.NOT_FOUND_MEMBER));
}

private void verifyUniqueFcmToken(String fcmToken, Long memberId) {
if (fcmRepository.findByToken(fcmToken, memberId).isPresent()) {
throw new ConflictException(FcmErrorCode.CONFLICT_FCM_TOKEN);
}
}

@Transactional
public FcmDeleteResponse deleteToken(Long fcmTokenId) {
int deleteCount = fcmRepository.deleteByFcmTokenId(fcmTokenId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.BDDMockito.*;

import java.time.LocalDateTime;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -17,11 +19,13 @@
import com.google.firebase.messaging.Message;

import codesquad.fineants.domain.fcm_token.FcmRepository;
import codesquad.fineants.domain.fcm_token.FcmToken;
import codesquad.fineants.domain.member.Member;
import codesquad.fineants.domain.member.MemberRepository;
import codesquad.fineants.domain.oauth.support.AuthMember;
import codesquad.fineants.spring.api.errors.errorcode.FcmErrorCode;
import codesquad.fineants.spring.api.errors.exception.BadRequestException;
import codesquad.fineants.spring.api.errors.exception.ConflictException;
import codesquad.fineants.spring.api.fcm.request.FcmRegisterRequest;
import codesquad.fineants.spring.api.fcm.response.FcmRegisterResponse;

Expand Down Expand Up @@ -88,6 +92,28 @@ void registerToken_whenInvalidToken_thenThrow400Error() throws FirebaseMessaging
.hasMessage(FcmErrorCode.BAD_REQUEST_FCM_TOKEN.getMessage());
}

@DisplayName("사용자는 이미 동일한 FCM 토큰이 존재하면 등록할 수 없다")
@Test
void registerToken_whenAlreadyFcmToken_thenThrow409Error() {
// given
Member member = memberRepository.save(createMember());
fcmRepository.save(FcmToken.builder()
.latestActivationTime(LocalDateTime.now())
.token("fcmToken")
.member(member)
.build());
FcmRegisterRequest request = FcmRegisterRequest.builder()
.fcmToken("fcmToken")
.build();
// when
Throwable throwable = catchThrowable(() -> fcmService.registerToken(request, AuthMember.from(member)));

// then
assertThat(throwable)
.isInstanceOf(ConflictException.class)
.hasMessage(FcmErrorCode.CONFLICT_FCM_TOKEN.getMessage());
}

private Member createMember() {
return Member.builder()
.nickname("nemo1234")
Expand Down