Skip to content
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
Expand Up @@ -7,6 +7,7 @@
import com.jiwon.mylog.domain.category.dto.response.CategoryResponse;
import com.jiwon.mylog.domain.category.dto.request.CategoryRequest;
import com.jiwon.mylog.domain.category.repository.CategoryRepository;
import com.jiwon.mylog.domain.post.repository.PostRepository;
import com.jiwon.mylog.domain.user.entity.User;
import com.jiwon.mylog.global.common.error.exception.DuplicateException;
import com.jiwon.mylog.global.common.error.ErrorCode;
Expand All @@ -24,6 +25,7 @@ public class CategoryService {

private final CategoryRepository categoryRepository;
private final UserRepository userRepository;
private final PostRepository postRepository;

@Transactional
public CategoryResponse createCategory(Long userId, CategoryRequest categoryRequest) {
Expand All @@ -48,6 +50,7 @@ public CategoryResponse updateCategory(Long userId, Long categoryId, CategoryReq
@Transactional
public void deleteCategory(Long userId, Long categoryId) {
Category category = getUserCategory(userId, categoryId);
postRepository.updatePostCategory(categoryId);
categoryRepository.delete(category);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.jiwon.mylog.domain.event;

import com.jiwon.mylog.domain.event.dto.CommentCreatedEvent;
import com.jiwon.mylog.domain.event.dto.FollowCreatedEvent;
import com.jiwon.mylog.domain.event.dto.FollowDeletedEvent;
import com.jiwon.mylog.domain.event.dto.LikeCreatedEvent;
import com.jiwon.mylog.domain.notification.entity.Notification;
import com.jiwon.mylog.domain.notification.repository.NotificationRepository;
Expand Down Expand Up @@ -29,8 +31,7 @@ public class NotificationEventListener {
@EventListener
public void handleCommentCreated(CommentCreatedEvent event) {
Long receiverId = event.getPostWriterId();
User receiver = userRepository.findById(receiverId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_USER));
User receiver = getReceiver(receiverId);

Notification notification = Notification.create(
receiver,
Expand All @@ -40,19 +41,14 @@ public void handleCommentCreated(CommentCreatedEvent event) {
);
notificationRepository.save(notification);

try {
notificationService.sendNotification(receiverId, notification);
} catch(Exception e) {
log.warn("SSE 전송 실패");
}
sendSSE(receiverId, notification);
}

@Transactional
@EventListener
public void handleLikeCreated(LikeCreatedEvent event) {
Long receiverId = event.getPostWriterId();
User receiver = userRepository.findById(receiverId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_USER));
User receiver = getReceiver(receiverId);

Notification notification = Notification.create(
receiver,
Expand All @@ -62,6 +58,49 @@ public void handleLikeCreated(LikeCreatedEvent event) {
);
notificationRepository.save(notification);

sendSSE(receiverId, notification);
}

@Transactional
@EventListener
public void handleFollowCreated(FollowCreatedEvent event) {
Long receiverId = event.getReceiverId();
User receiver = getReceiver(event.getReceiverId());

Notification notification = Notification.create(
receiver,
event.getFollowerName() + "왹이 잡 았다! 너 잡혔다!",
"/" + event.getFollowerId(),
NotificationType.FOLLOW
);
notificationRepository.save(notification);

sendSSE(receiverId, notification);
}

@Transactional
@EventListener
public void handleUnFollowCreated(FollowDeletedEvent event) {
Long receiverId = event.getReceiverId();
User receiver = getReceiver(receiverId);

Notification notification = Notification.create(
receiver,
"오오자비로운" + event.getFollowerName() + "왹께서널놓아주시니",
"/" + event.getFollowerId(),
NotificationType.FOLLOW
);
notificationRepository.save(notification);

sendSSE(receiverId, notification);
}

private User getReceiver(Long receiverId) {
return userRepository.findById(receiverId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_USER));
}

private void sendSSE(Long receiverId, Notification notification) {
try {
notificationService.sendNotification(receiverId, notification);
} catch(Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.jiwon.mylog.domain.event.dto;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class FollowCreatedEvent {
private final Long receiverId;
private final Long followerId;
private final String followerName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.jiwon.mylog.domain.event.dto;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class FollowDeletedEvent {
private final Long receiverId;
private final Long followerId;
private final String followerName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
import jakarta.persistence.ManyToOne;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
public interface FollowRepository extends JpaRepository<Follow, Long> {
boolean existsByFromUserIdAndToUserId(Long fromUserId, Long toUserId);

Optional<Follow> findByFromUserIdAndToUserId(Long fromUserId, Long toUserId);
@Query("select f from Follow f " +
"join fetch f.fromUser " +
"where f.fromUser.id = :fromUserId and f.toUser.id = :toUserId")
Optional<Follow> findByFromUserIdAndToUserId(@Param("fromUserId") Long fromUserId, @Param("toUserId") Long toUserId);

@Query("select " +
"sum(case when f.fromUser.id = :userId then 1 else 0 end), " +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.jiwon.mylog.domain.follow.service;

import com.jiwon.mylog.domain.event.dto.FollowCreatedEvent;
import com.jiwon.mylog.domain.event.dto.FollowDeletedEvent;
import com.jiwon.mylog.domain.follow.dto.FollowCountResponse;
import com.jiwon.mylog.domain.follow.dto.FollowListResponse;
import com.jiwon.mylog.domain.follow.dto.FollowResponse;
Expand All @@ -10,6 +12,7 @@
import com.jiwon.mylog.global.common.error.ErrorCode;
import com.jiwon.mylog.global.common.error.exception.NotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -19,6 +22,7 @@
@Service
public class FollowService {

private final ApplicationEventPublisher eventPublisher;
private final UserRepository userRepository;
private final FollowRepository followRepository;

Expand All @@ -33,6 +37,16 @@ public void follow(Long fromUserId, Long toUserId) {
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_USER));

followRepository.save(Follow.follow(fromUser, toUser));

if (toUser.getId() != null) {
eventPublisher.publishEvent(
new FollowCreatedEvent(
toUser.getId(),
fromUser.getId(),
fromUser.getUsername()
)
);
}
}

@Transactional
Expand All @@ -44,6 +58,16 @@ public void unfollow(Long fromUserId, Long toUserId) {
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND));

followRepository.delete(follow);

if (toUserId != null) {
eventPublisher.publishEvent(
new FollowDeletedEvent(
toUserId,
fromUserId,
follow.getFromUser().getUsername()
)
);
}
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public SseEmitter subscribe(
HttpServletResponse response) {

if (accessToken == null || !jwtService.validateToken(accessToken)) {
throw new UnauthorizedException(ErrorCode.UNAUTHORIZED);
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
}

response.setHeader("Cache-Control", "no-cache");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface NotificationRepository extends JpaRepository<Notification, Long> {

@Modifying
@Query("delete from Notification n where n.isRead = true and n.createdAt < :date")
void deleteAllByCreatedAtBefore(@Param("date") LocalDateTime date);

@Modifying(clearAutomatically = true)
@Query("update Notification n set n.isRead = true where n.receiver.id = :receiverId and n.isRead = false")
void updateReadStateByReceiverId(@Param("receiverId") Long receiverId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public ResponseEntity<String> hello(@LoginUser Long userId) {
public ResponseEntity<PostDetailResponse> createNotice(
@LoginUser Long userId,
@Valid @RequestBody PostRequest postRequest) {
PostDetailResponse response = postService.createPost(userId, postRequest, true);
PostDetailResponse response = postService.createPost(userId, postRequest);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}

Expand All @@ -65,7 +65,7 @@ public ResponseEntity<PostDetailResponse> updateNotice(
@LoginUser Long userId,
@PathVariable("postId") Long postId,
@Valid @RequestBody PostRequest postRequest) {
PostDetailResponse response = postService.updatePost(userId, postId, postRequest, true);
PostDetailResponse response = postService.updatePost(userId, postId, postRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class PostController {
public ResponseEntity<PostDetailResponse> createPost(
@LoginUser Long userId,
@Valid @RequestBody PostRequest postRequest) {
PostDetailResponse response = postService.createPost(userId, postRequest, false);
PostDetailResponse response = postService.createPost(userId, postRequest);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}

Expand All @@ -66,7 +66,7 @@ public ResponseEntity<PostDetailResponse> updatePost(
@LoginUser Long userId,
@PathVariable("postId") Long postId,
@Valid @RequestBody PostRequest postRequest) {
PostDetailResponse response = postService.updatePost(userId, postId, postRequest, false);
PostDetailResponse response = postService.updatePost(userId, postId, postRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ public class PostRequest {
private List<@Valid TagRequest> tagRequests = new ArrayList<>();

private boolean pinned;

@NotBlank(message = "게시글 타입을 지정해주세요.")
private String type;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.jiwon.mylog.domain.category.dto.response.CategoryResponse;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.tag.dto.response.TagResponse;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

Expand All @@ -13,6 +14,12 @@ public class PinnedPostResponse {
private final String title;
private final String contentPreview;

public PinnedPostResponse(Long postId, String title, String contentPreview) {
this.postId = postId;
this.title = title;
this.contentPreview = contentPreview;
}

public static PinnedPostResponse fromPost(Post post) {
return PinnedPostResponse.builder()
.postId(post.getId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonFormat;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.post.entity.PostType;
import com.jiwon.mylog.global.common.enums.Visibility;
import com.jiwon.mylog.domain.category.dto.response.CategoryResponse;
import com.jiwon.mylog.domain.comment.dto.response.CommentResponse;
Expand Down Expand Up @@ -30,13 +31,13 @@ public class PostDetailResponse {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
private boolean pinned;
private boolean isNotice;
private PostType type;
private UserResponse user;
private CategoryResponse category;
private List<TagResponse> tags;
private List<CommentResponse> comments;

public PostDetailResponse(Long postId, String title, String content, String contentPreview, int views, PostStatus postStatus, Visibility visibility, LocalDateTime createdAt, boolean pinned, boolean isNotice, UserResponse user, CategoryResponse category) {
public PostDetailResponse(Long postId, String title, String content, String contentPreview, int views, PostStatus postStatus, Visibility visibility, LocalDateTime createdAt, boolean pinned, PostType type, UserResponse user, CategoryResponse category) {
this.postId = postId;
this.title = title;
this.content = content;
Expand All @@ -46,7 +47,7 @@ public PostDetailResponse(Long postId, String title, String content, String cont
this.visibility = visibility;
this.createdAt = createdAt;
this.pinned = pinned;
this.isNotice = isNotice;
this.type = type;
this.user = user;
this.category = category;
}
Expand All @@ -67,7 +68,7 @@ public static PostDetailResponse fromPost(Post post) {
.toList())
.createdAt(post.getCreatedAt())
.pinned(post.isPinned())
.isNotice(post.isNotice())
.type(post.getType())
.comments(post.getComments().stream()
.map(comment -> CommentResponse.fromComment(comment))
.toList())
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/com/jiwon/mylog/domain/post/entity/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ public class Post extends BaseEntity {
@Builder.Default
private boolean pinned = false;

@Builder.Default
private boolean isNotice = false;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private PostType type;

@Enumerated(value = EnumType.STRING)
private PostStatus postStatus;
Expand Down Expand Up @@ -85,7 +86,7 @@ public class Post extends BaseEntity {
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();

public static Post create(PostRequest request, boolean isNotice, User user, Category category, List<Tag> tags) {
public static Post create(PostRequest request, User user, Category category, List<Tag> tags) {
Post post = Post.builder()
.title(request.getTitle())
.content(request.getContent())
Expand All @@ -95,7 +96,7 @@ public static Post create(PostRequest request, boolean isNotice, User user, Cate
.user(user)
.category(category)
.pinned(request.isPinned())
.isNotice(isNotice)
.type(PostType.fromString(request.getType()))
.build();
post.setTags(tags);
return post;
Expand Down
Loading