Skip to content

Commit

Permalink
[FEAT] 알림 구현 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
ohksj77 committed Dec 29, 2023
1 parent 5d35fd0 commit 47929b3
Show file tree
Hide file tree
Showing 23 changed files with 237 additions and 117 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.twtw.backend.config.converter;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConverterConfig {

@Bean
public Jackson2JsonMessageConverter jsonMessageConverter(){
return new Jackson2JsonMessageConverter();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.twtw.backend.config.rabbitmq;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.twtw.backend.global.constant.RabbitMQConstant;
import com.twtw.backend.global.properties.RabbitMQProperties;

import lombok.RequiredArgsConstructor;
Expand All @@ -23,25 +24,39 @@
@RequiredArgsConstructor
public class RabbitMQConfig {

private static final String QUEUE_NAME = "map.queue";
private static final String EXCHANGE_NAME = "map";
private static final String ROUTING_KEY = "plan.*";
private final RabbitMQProperties rabbitMQProperties;
private final ObjectMapper objectMapper;

@Bean
public Queue queue() {
return new Queue(QUEUE_NAME, true);
public Queue locationQueue() {
return new Queue(RabbitMQConstant.LOCATION_QUEUE.getName(), true);
}

@Bean
public TopicExchange topicExchange() {
return new TopicExchange(EXCHANGE_NAME);
public TopicExchange locationTopicExchange() {
return new TopicExchange(RabbitMQConstant.LOCATION_EXCHANGE.getName());
}

@Bean
public Binding binding(final Queue queue, final TopicExchange topicExchange) {
return BindingBuilder.bind(queue).to(topicExchange).with(ROUTING_KEY);
public Binding locationBinding() {
return BindingBuilder.bind(locationQueue()).to(locationTopicExchange())
.with(RabbitMQConstant.LOCATION_ROUTING_KEY.getName());
}

@Bean
public Queue notificationQueue() {
return new Queue(RabbitMQConstant.NOTIFICATION_QUEUE.getName(), true);
}

@Bean
public TopicExchange notificationTopicExchange() {
return new TopicExchange(RabbitMQConstant.NOTIFICATION_EXCHANGE.getName());
}

@Bean
public Binding notificationBinding() {
return BindingBuilder.bind(notificationQueue()).to(notificationTopicExchange())
.with(RabbitMQConstant.NOTIFICATION_ROUTING_KEY.getName());
}

@Bean
Expand All @@ -63,20 +78,21 @@ public Jackson2JsonMessageConverter jsonMessageConverter() {
public RabbitTemplate rabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(QUEUE_NAME);
return rabbitTemplate;
}

@Bean
public RabbitAdmin rabbitAdmin(
final ConnectionFactory connectionFactory,
final Queue queue,
final TopicExchange topicExchange,
final Binding binding) {
final ConnectionFactory connectionFactory) {
final RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
rabbitAdmin.declareQueue(queue);
rabbitAdmin.declareExchange(topicExchange);
rabbitAdmin.declareBinding(binding);

rabbitAdmin.declareQueue(locationQueue());
rabbitAdmin.declareExchange(locationTopicExchange());
rabbitAdmin.declareBinding(locationBinding());

rabbitAdmin.declareQueue(notificationQueue());
rabbitAdmin.declareExchange(notificationTopicExchange());
rabbitAdmin.declareBinding(notificationBinding());
return rabbitAdmin;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
import com.twtw.backend.domain.member.entity.Member;
import com.twtw.backend.domain.member.service.AuthService;
import com.twtw.backend.domain.member.service.MemberService;
import com.twtw.backend.domain.notification.dto.NotificationRequest;
import com.twtw.backend.domain.notification.messagequeue.FcmProducer;
import com.twtw.backend.global.constant.NotificationBody;
import com.twtw.backend.global.constant.NotificationTitle;
import com.twtw.backend.global.exception.EntityNotFoundException;

import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -27,11 +29,22 @@ public class FriendService {
private final FriendMapper friendMapper;
private final MemberService memberService;
private final AuthService authService;
private final FcmProducer fcmProducer;

public void addRequest(final FriendRequest friendRequest) {
final Member loginMember = authService.getMemberByJwt();
final Member member = memberService.getMemberById(friendRequest.getMemberId());
friendRepository.save(friendMapper.toEntity(loginMember, member));

sendNotification(member.getDeviceTokenValue(), loginMember.getNickname());
}

private void sendNotification(final String deviceToken, final String nickname) {
fcmProducer.sendNotification(
new NotificationRequest(
deviceToken,
NotificationTitle.FRIEND_REQUEST_TITLE.getName(),
NotificationBody.FRIEND_REQUEST_BODY.toNotificationBody(nickname)));
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import com.twtw.backend.domain.member.entity.Member;
import com.twtw.backend.domain.member.service.AuthService;
import com.twtw.backend.domain.member.service.MemberService;
import com.twtw.backend.domain.notification.service.FcmService;
import com.twtw.backend.domain.notification.dto.NotificationRequest;
import com.twtw.backend.domain.notification.messagequeue.FcmProducer;
import com.twtw.backend.global.constant.NotificationBody;
import com.twtw.backend.global.constant.NotificationTitle;
import com.twtw.backend.global.exception.EntityNotFoundException;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -27,25 +29,23 @@ public class GroupService {
private final GroupRepository groupRepository;
private final GroupMemberRepository groupMemberRepository;
private final AuthService authService;

private final MemberService memberService;
private final GroupMapper groupMapper;

private final FcmService fcmService;
private final FcmProducer fcmProducer;

public GroupService(
GroupRepository groupRepository,
GroupMemberRepository groupMemberRepository,
AuthService authService,
MemberService memberService,
GroupMapper groupMapper,
FcmService fcmService) {
FcmProducer fcmProducer) {
this.groupRepository = groupRepository;
this.groupMemberRepository = groupMemberRepository;
this.authService = authService;
this.memberService = memberService;
this.groupMapper = groupMapper;
this.fcmService = fcmService;
this.fcmProducer = fcmProducer;
}

public GroupInfoResponse getGroupById(UUID groupId) {
Expand Down Expand Up @@ -117,11 +117,20 @@ public GroupInfoResponse inviteGroup(InviteGroupRequest inviteGroupRequest) {
memberService.getMembersByIds(inviteGroupRequest.getFriendMemberIds());
group.inviteAll(friends);

// invite push Alert
String groupName = group.getName();
friends.forEach(friend -> sendNotification(friend.getDeviceTokenValue(), groupName));

return groupMapper.toGroupInfo(group);
}

private void sendNotification(final String deviceToken, final String groupName) {
fcmProducer.sendNotification(
new NotificationRequest(
deviceToken,
NotificationTitle.GROUP_REQUEST_TITLE.getName(),
NotificationBody.GROUP_REQUEST_BODY.toNotificationBody(groupName)));
}

public GroupInfoResponse getGroupInfoResponse(Group group) {
return groupMapper.toGroupInfo(group);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.twtw.backend.domain.location.dto.request.LocationRequest;
import com.twtw.backend.domain.location.service.LocationService;

import com.twtw.backend.global.constant.RabbitMQConstant;
import lombok.RequiredArgsConstructor;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
Expand All @@ -17,8 +18,6 @@
@RequiredArgsConstructor
public class LocationController {

private static final String EXCHANGE_NAME = "map";
private static final String ROUTING_KEY = "plan.";
private final RabbitTemplate rabbitTemplate;
private final LocationService locationService;

Expand All @@ -27,8 +26,8 @@ public void share(
@DestinationVariable final UUID planId,
@Payload final LocationRequest locationRequest) {
rabbitTemplate.convertAndSend(
EXCHANGE_NAME,
ROUTING_KEY + planId,
RabbitMQConstant.LOCATION_EXCHANGE.getName(),
RabbitMQConstant.LOCATION_ROUTING_KEY_PREFIX.getName() + planId,
locationService.addInfo(planId, locationRequest));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public ResponseEntity<AfterLoginResponse> afterSocialLogin(
}

@PostMapping("/device")
public ResponseEntity<Void> saveDeviceToken(@RequestBody DeviceTokenRequest request) {
authService.saveDeviceToken(request);
public ResponseEntity<Void> updateDeviceToken(@RequestBody DeviceTokenRequest request) {
authService.updateDeviceToken(request);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public ResponseEntity<DuplicateNicknameResponse> duplicateNickname(@PathVariable
return ResponseEntity.ok(memberService.duplicateNickname(name));
}

@GetMapping()
@GetMapping
public ResponseEntity<SearchMemberResponse> searchMemberByNickname(
@RequestParam(name = "nickname") String nickname) {
return ResponseEntity.ok(memberService.getMemberByNickname(nickname));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.twtw.backend.domain.member.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -12,7 +10,7 @@
@AllArgsConstructor
public class MemberSaveRequest {
@NotBlank private String nickname;
@NotNull private String profileImage;

@NotBlank private String profileImage;
@NotBlank private String deviceToken;
private OAuthRequest oauthRequest;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public DeviceToken(String deviceToken) {
this.deviceToken = deviceToken;
}

public void setMember(Member member) {
public void organizeMember(Member member) {
this.member = member;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public class Member implements Auditable {
@OneToMany(mappedBy = "member")
private List<GroupMember> groupMembers = new ArrayList<>();

@OneToOne
@JoinColumn(name = "device_token")
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn
private DeviceToken deviceToken;

@Setter
Expand All @@ -53,11 +53,12 @@ public class Member implements Auditable {
private BaseTime baseTime;

@Builder
public Member(String nickname, String profileImage, OAuth2Info oauthInfo) {
public Member(String nickname, String profileImage, OAuth2Info oauthInfo, String deviceToken) {
this.nickname = nickname;
this.profileImage = profileImage;
this.role = Role.ROLE_USER;
this.oauthInfo = oauthInfo;
updateDeviceToken(new DeviceToken(deviceToken));
}

public void addGroupMember(final GroupMember groupMember) {
Expand All @@ -74,6 +75,10 @@ public void updateProfileImage(final String profileImage) {

public void updateDeviceToken(final DeviceToken deviceToken) {
this.deviceToken = deviceToken;
deviceToken.setMember(this);
deviceToken.organizeMember(this);
}

public String getDeviceTokenValue() {
return this.deviceToken.getDeviceToken();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
import com.twtw.backend.domain.member.exception.RefreshTokenInfoMismatchException;
import com.twtw.backend.domain.member.exception.RefreshTokenValidationException;
import com.twtw.backend.domain.member.mapper.MemberMapper;
import com.twtw.backend.domain.member.repository.DeviceTokenRepository;
import com.twtw.backend.domain.member.repository.MemberRepository;
import com.twtw.backend.domain.member.repository.RefreshTokenRepository;
import com.twtw.backend.global.exception.EntityNotFoundException;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
Expand All @@ -34,19 +32,16 @@ public class AuthService {
private final MemberRepository memberRepository;
private final RefreshTokenRepository refreshTokenRepository;

private final DeviceTokenRepository deviceTokenRepository;
private final TokenProvider tokenProvider;
private final MemberMapper memberMapper;

public AuthService(
MemberRepository memberRepository,
RefreshTokenRepository refreshTokenRepository,
DeviceTokenRepository deviceTokenRepository,
TokenProvider tokenProvider,
MemberMapper memberMapper) {
this.memberRepository = memberRepository;
this.refreshTokenRepository = refreshTokenRepository;
this.deviceTokenRepository = deviceTokenRepository;
this.tokenProvider = tokenProvider;
this.memberMapper = memberMapper;
}
Expand Down Expand Up @@ -141,20 +136,13 @@ public Member getMemberByJwt() {

UUID id = UUID.fromString(authentication.getName());

Optional<Member> member = memberRepository.findById(id);

if (member.isPresent()) {
return member.get();
}

throw new EntityNotFoundException();
return memberRepository.findById(id).orElseThrow(EntityNotFoundException::new);
}

@Transactional
public void saveDeviceToken(DeviceTokenRequest request) {
public void updateDeviceToken(DeviceTokenRequest request) {
Member member = getMemberByJwt();
DeviceToken deviceToken = new DeviceToken(request.getDeviceToken());
member.updateDeviceToken(deviceToken);
deviceTokenRepository.save(deviceToken);
}
}
Loading

0 comments on commit 47929b3

Please sign in to comment.