Skip to content

Commit

Permalink
Merge pull request #79 from prgrms-web-devcourse/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
sangmin7648 authored Jan 21, 2022
2 parents 7ce18a7 + ded6404 commit 78a6aba
Show file tree
Hide file tree
Showing 21 changed files with 657 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.prgrms.modi.notification.controller;

import com.prgrms.modi.common.jwt.JwtAuthentication;
import com.prgrms.modi.error.exception.InvalidAuthenticationException;
import com.prgrms.modi.notification.dto.NotificationsResponse;
import com.prgrms.modi.notification.service.NotificationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import springfox.documentation.annotations.ApiIgnore;

@RestController
@RequestMapping("/api/notifications")
public class NotificationController {

private final NotificationService notificationService;

public NotificationController(NotificationService notificationService) {
this.notificationService = notificationService;
}

@GetMapping(path = "/subscribe/{userId}", produces = "text/event-stream;charset=UTF-8")
@Operation(summary = "로그인한 유저 sse 연결")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "유저 sse 연결 성공 (OK)")
})
public SseEmitter subscribe(
@Parameter(description = "유저의 ID") @PathVariable Long userId,
@RequestHeader(value = "Last-Event-ID", required = false, defaultValue = "") String lastEventId
) {
return notificationService.subscribe(userId, lastEventId);
}

@GetMapping
@Operation(summary = "로그인한 유저의 모든 알림 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "모든 알림 조회 성공 (OK)")
})
public ResponseEntity<NotificationsResponse> getNotifications(
@ApiIgnore @AuthenticationPrincipal JwtAuthentication authentication
) {
if (authentication == null) {
throw new InvalidAuthenticationException("인증되지 않는 사용자입니다");
}
NotificationsResponse resp = notificationService.findAllById(authentication.userId);
return ResponseEntity.ok(resp);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.prgrms.modi.notification.domain;

import com.prgrms.modi.party.domain.Party;
import com.prgrms.modi.user.domain.Member;
import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.lang3.builder.ToStringBuilder;

@Entity
@Table(name = "notifications")
public class Notification {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;

private String content;

private boolean readCheck;

private LocalDateTime createdAt;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "party_id")
private Party party;

protected Notification() {
}

public Notification(String content, boolean isRead, Member member, Party party) {
this.content = content;
this.readCheck = isRead;
this.createdAt = LocalDateTime.now();
this.member = member;
this.party = party;
}

public void read() {
this.readCheck = true;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}

public Long getId() {
return id;
}

public String getContent() {
return content;
}

public boolean getReadCheck() {
return readCheck;
}

public Member getMember() {
return member;
}

public Party getParty() {
return party;
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("content", content)
.append("readCheck", readCheck)
.append("createdAt", createdAt)
.append("member", member)
.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.prgrms.modi.notification.dto;

import com.prgrms.modi.notification.domain.Notification;
import com.prgrms.modi.user.domain.Member;
import java.time.LocalDateTime;
import java.util.List;

public class NotificationResponse implements Comparable<NotificationResponse> {

private Long id;

private String content;

private LocalDateTime createdAt;

private boolean readCheck;

private Long partyId;

private String partyLeaderName;

private String ottName;

private NotificationResponse(Long id, String content, LocalDateTime createdAt, boolean readCheck,
Long partyId, String partyLeaderName, String ottName) {
this.id = id;
this.content = content;
this.createdAt = createdAt;
this.readCheck = readCheck;
this.partyId = partyId;
this.partyLeaderName = partyLeaderName;
this.ottName = ottName;
}

public static NotificationResponse from(Notification notification) {
List<Member> members = notification.getParty().getMembers();
Member leader = null;
for (Member member : members) {
if (member.isLeader()) {
leader = member;
}
}
return new NotificationResponse(notification.getId(), notification.getContent(), notification.getCreatedAt(),
notification.getReadCheck(), notification.getParty().getId(), leader.getUser().getUsername(),
notification.getParty().getOtt().getName()
);
}

public Long getId() {
return id;
}

public String getContent() {
return content;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}

public boolean isReadCheck() {
return readCheck;
}

public Long getPartyId() {
return partyId;
}

public String getPartyLeaderName() {
return partyLeaderName;
}

public String getOttName() {
return ottName;
}

@Override
public int compareTo(NotificationResponse o) {
if (this.getId() > o.getId()) {
return -1;
} else if (this.getId() < o.getId()) {
return 1;
}
return 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.prgrms.modi.notification.dto;

import java.util.List;

public class NotificationsResponse {

private List<NotificationResponse> notificationResponseList;

private long unreadCount;

public List<NotificationResponse> getNotificationResponseList() {
return notificationResponseList;
}

public long getUnreadCount() {
return unreadCount;
}

private NotificationsResponse(
List<NotificationResponse> notificationResponseList, long unreadCount) {
this.notificationResponseList = notificationResponseList;
this.unreadCount = unreadCount;
}

public static NotificationsResponse of(List<NotificationResponse> notificationResponses, long unreadCount) {
return new NotificationsResponse(notificationResponses, unreadCount);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.prgrms.modi.notification.repository;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.springframework.stereotype.Repository;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

@Repository
public class EmitterRepository {

public final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

private final Map<String, Object> eventCache = new ConcurrentHashMap<>();

public SseEmitter save(String id, SseEmitter sseEmitter) {
emitters.put(id, sseEmitter);
return sseEmitter;
}

public void deleteById(String id) {
emitters.remove(id);
}

public Map<String, Object> findAllEventCacheStartWithId(String id) {
return eventCache.entrySet().stream()
.filter(entry -> entry.getKey().startsWith(id))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

public void saveEventCache(String id, Object event) {
eventCache.put(id, event);
}

public Map<String, SseEmitter> findAllStartWithById(String id) {
return emitters.entrySet().stream()
.filter(entry -> entry.getKey().startsWith(id))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.prgrms.modi.notification.repository;

import com.prgrms.modi.notification.domain.Notification;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface NotificationRepository extends JpaRepository<Notification, Long> {

List<Notification> findByMemberIdAndReadCheckFalse(Long memberId);

}
Loading

0 comments on commit 78a6aba

Please sign in to comment.