-
Notifications
You must be signed in to change notification settings - Fork 3
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
feat: FCM을 통해 푸쉬 알림 구현 #605
Changes from 51 commits
816bc5b
c30da47
871f31f
71fabe2
87f7b6c
68afe3d
3e4fb84
1847365
0a56f86
8e37b6d
232a9e8
56ed9ed
7bdac86
b5343c1
d52123c
59395fa
243a543
2fbc056
e9ae177
fb58174
345e26b
a54c98e
67b60cc
7411239
96dd81a
a9a108b
3260191
de6ca3b
6bc9632
cfd043d
508a0d2
68dba79
d2fed6d
100e58b
0366b0f
a0a9ba1
062cd3e
c512f4f
81b712c
3943410
ea7b88f
c85389f
858a368
d949417
8ac44a5
1f54e5f
116661a
ee4e255
5876b95
e3a0f94
6aec78f
1108ade
4272d0f
47872ab
beccb98
bca5963
9ade0e7
3c9868d
52adfe6
73b416e
810486a
90edf36
bdce767
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,4 +46,4 @@ openapi3.yaml | |
.idea | ||
|
||
### FCM ### | ||
/src/main/resources/fcm | ||
/src/main/resources/fcm |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,27 +11,33 @@ | |
import com.zzang.chongdae.member.repository.MemberRepository; | ||
import com.zzang.chongdae.member.repository.entity.MemberEntity; | ||
import com.zzang.chongdae.member.service.NicknameGenerator; | ||
import com.zzang.chongdae.notification.service.FcmNotificationService; | ||
import java.util.UUID; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Slf4j | ||
@RequiredArgsConstructor | ||
@Service | ||
public class AuthService { | ||
|
||
private final FcmNotificationService notificationService; | ||
private final MemberRepository memberRepository; | ||
private final PasswordEncoder passwordEncoder; | ||
private final JwtTokenProvider jwtTokenProvider; | ||
private final NicknameGenerator nickNameGenerator; | ||
private final AuthClient authClient; | ||
|
||
@WriterDatabase | ||
@Transactional | ||
public AuthInfoDto kakaoLogin(KakaoLoginRequest request) { | ||
String loginId = authClient.getKakaoUserInfo(request.accessToken()); | ||
AuthProvider provider = AuthProvider.KAKAO; | ||
MemberEntity member = memberRepository.findByLoginId(loginId) | ||
.orElseGet(() -> signup(provider, loginId, request.fcmToken())); | ||
return login(member); | ||
return login(member, request.fcmToken()); | ||
} | ||
|
||
private MemberEntity signup(AuthProvider provider, String loginId, String fcmToken) { | ||
|
@@ -40,12 +46,21 @@ private MemberEntity signup(AuthProvider provider, String loginId, String fcmTok | |
return memberRepository.save(member); | ||
} | ||
|
||
private AuthInfoDto login(MemberEntity member) { | ||
private AuthInfoDto login(MemberEntity member, String fcmToken) { | ||
AuthMemberDto authMember = new AuthMemberDto(member); | ||
AuthTokenDto authToken = jwtTokenProvider.createAuthToken(member.getId().toString()); | ||
checkFcmToken(member, fcmToken); | ||
notificationService.login(member); | ||
return new AuthInfoDto(authMember, authToken); | ||
} | ||
|
||
private void checkFcmToken(MemberEntity member, String fcmToken) { | ||
if (!memberRepository.existsByIdAndFcmToken(member.getId(), fcmToken)) { | ||
log.info("토큰 갱신 사용자 id: {}", member.getId()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 로그는 빼는게 어떨까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에서 포케의 리뷰에 작성해둔 부분 참고해주세요 :-) 감사합니다 |
||
member.updateFcmToken(fcmToken); | ||
} | ||
} | ||
|
||
public AuthTokenDto refresh(String refreshToken) { | ||
Long memberId = jwtTokenProvider.getMemberIdByRefreshToken(refreshToken); | ||
return jwtTokenProvider.createAuthToken(memberId.toString()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
package com.zzang.chongdae.auth.service.dto; | ||
|
||
import javax.annotation.Nullable; | ||
import jakarta.validation.constraints.NotEmpty; | ||
|
||
public record KakaoLoginRequest(String accessToken, | ||
|
||
@Nullable | ||
@NotEmpty | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 회의 때 Nullable에서 NotEmpty로 바뀐 배경이 궁금했어요 😄 이전 버전을 사용하는 사용자들이 fcmToken을 전달하지 않으면 어떻게 되나요? 기존에 fcmtoken을 전달하지 않은 사용자들은 어떻게 처리되나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
String fcmToken) { | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,30 @@ | ||
package com.zzang.chongdae.notification.domain; | ||
|
||
import com.zzang.chongdae.offering.repository.entity.OfferingEntity; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 어노테이션은 |
||
@Getter | ||
@RequiredArgsConstructor | ||
public class FcmCondition { | ||
|
||
private static final String CONDITION_FORMAT_TRUE_AND_FALSE = "'%s' in topics && !('%s' in topics)"; | ||
|
||
private final String value; | ||
|
||
public static FcmCondition roomStatusCondition(OfferingEntity offering) { | ||
FcmTopic offeringTopic = FcmTopic.offeringMemberTopic(offering); | ||
FcmTopic proposerTopic = FcmTopic.proposerTopic(offering); | ||
String value = CONDITION_FORMAT_TRUE_AND_FALSE.formatted(offeringTopic.getValue(), proposerTopic.getValue()); | ||
return new FcmCondition(value); | ||
} | ||
|
||
public static FcmCondition offeringCondition(OfferingEntity offering) { | ||
FcmTopic memberTopic = FcmTopic.memberTopic(); | ||
FcmTopic proposerTopic = FcmTopic.proposerTopic(offering); | ||
String value = CONDITION_FORMAT_TRUE_AND_FALSE.formatted(memberTopic.getValue(), proposerTopic.getValue()); | ||
return new FcmCondition(value); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.zzang.chongdae.notification.domain; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
public class FcmData { | ||
|
||
private final Map<String, String> data = new HashMap<>(); | ||
|
||
public void addData(String key, Object value) { | ||
data.put(key, value.toString()); | ||
} | ||
|
||
public Map<String, String> getData() { | ||
data.forEach((key, value) -> log.info("{} : {}", key, value)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 로그도 빼는 건 어떨까요? |
||
return Collections.unmodifiableMap(data); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,14 @@ | ||
package com.zzang.chongdae.notification.domain; | ||
|
||
import com.zzang.chongdae.member.repository.entity.MemberEntity; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public class FcmToken { | ||
|
||
private final String value; | ||
|
||
public FcmToken(MemberEntity member) { | ||
this.value = member.getFcmToken(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.zzang.chongdae.notification.domain; | ||
|
||
import com.zzang.chongdae.offering.repository.entity.OfferingEntity; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정적팩터리 메서드를 사용하려고 설정하셨을까요? 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정확합니다! |
||
public class FcmTopic { | ||
|
||
private static final String TOPIC_FORMAT_MEMBER = "member"; | ||
private static final String TOPIC_FORMAT_OFFERING_MEMBER = "member_of_offering_%d"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 회의 때 논한대로 participant_of_offering_%d 로 변경합시다! |
||
private static final String TOPIC_FORMAT_OFFERING_PROPOSER = "proposer_of_offering_%d"; | ||
|
||
private final String value; | ||
|
||
public static FcmTopic offeringMemberTopic(OfferingEntity offering) { | ||
String value = TOPIC_FORMAT_OFFERING_MEMBER.formatted(offering.getId()); | ||
return new FcmTopic(value); | ||
} | ||
|
||
public static FcmTopic proposerTopic(OfferingEntity offering) { | ||
String value = TOPIC_FORMAT_OFFERING_PROPOSER.formatted(offering.getId()); | ||
return new FcmTopic(value); | ||
} | ||
|
||
public static FcmTopic memberTopic() { | ||
return new FcmTopic(TOPIC_FORMAT_MEMBER); | ||
} | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이전 버전 API 를 사용하는 앱에 대응하기 위해서 fcmToken이 null일 때 처리 추가합시다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위 방식을 통해 현재 DB 내 default 값(
"invalid" + UUID.randomUUID()
)으로 설정되도록 하였습니다!