Skip to content

Commit

Permalink
feat: #18 푸시 알림 등록 & 해제 기능 개발
Browse files Browse the repository at this point in the history
사용자별 푸시 알림 등록 & 해제 기능을 개발함.
  • Loading branch information
edgar6bf committed Jan 10, 2024
1 parent 9d679f9 commit c621b0d
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package site.packit.packit.domain.notification.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import site.packit.packit.domain.auth.principal.CustomUserPrincipal;
import site.packit.packit.domain.member.entity.Member;
import site.packit.packit.domain.member.service.MemberService;
import site.packit.packit.domain.notification.service.PushNotificationService;
import site.packit.packit.global.response.success.SuccessApiResponse;
import site.packit.packit.global.response.util.ResponseUtil;

import static org.springframework.http.HttpStatus.OK;

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

private final MemberService memberService;
private final PushNotificationService pushNotificationService;

public NotificationController(MemberService memberService, PushNotificationService pushNotificationService) {
this.memberService = memberService;
this.pushNotificationService = pushNotificationService;
}

@PostMapping
public ResponseEntity<SuccessApiResponse> addPushNotificationSubscriber(@AuthenticationPrincipal CustomUserPrincipal principal) {
Member member = memberService.getMember(principal.getName());
pushNotificationService.createSubscriber(member);

return ResponseUtil.successApiResponse(OK, "성공적으로 알림 수신이 설정되었습니다.");
}

@DeleteMapping
public ResponseEntity<SuccessApiResponse> deletePushNotificationSubscriber(@AuthenticationPrincipal CustomUserPrincipal principal) {
Member member = memberService.getMember(principal.getName());
pushNotificationService.deleteSubscriber(member);

return ResponseUtil.successApiResponse(OK, "성공적으로 알림 수신이 해제되었습니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package site.packit.packit.domain.notification.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import site.packit.packit.domain.member.entity.Member;
import site.packit.packit.global.audit.BaseTimeEntity;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class PushNotificationSubscriber extends BaseTimeEntity {

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

@OneToOne(fetch = FetchType.LAZY)
private Member member;

public PushNotificationSubscriber(Member member) {
this.member = member;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package site.packit.packit.domain.notification.exception;

import lombok.Getter;
import org.springframework.http.HttpStatus;
import site.packit.packit.global.exception.ErrorCode;

import static org.springframework.http.HttpStatus.*;

@Getter
public enum NotificationErrorCode implements ErrorCode {

PUSH_NOTIFICATION_SUBSCRIBER_NOT_FOUND("NT-C-001", NOT_FOUND, "푸시 알림 구독자 정보가 존재하지 않습니다."),
PUSH_NOTIFICATION_SUBSCRIBER_ALREADY_EXIST("NT-C-002", BAD_REQUEST, "푸시 알림 구독자 정보가 이미 존재합니다.");

private final String code;
private final HttpStatus httpStatus;
private final String message;

NotificationErrorCode(String code, HttpStatus httpStatus, String message) {
this.code = code;
this.httpStatus = httpStatus;
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package site.packit.packit.domain.notification.exception;

import site.packit.packit.global.exception.ErrorCode;

public class NotificationException extends RuntimeException {

private final ErrorCode errorCode;

public NotificationException(ErrorCode errorCode) {
this.errorCode = errorCode;
}

public ErrorCode getErrorCode() {
return errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package site.packit.packit.domain.notification.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import site.packit.packit.global.exception.ErrorCode;
import site.packit.packit.global.response.error.ErrorApiResponse;

@Slf4j
@RestControllerAdvice
public class NotificationExceptionHandler {

@ExceptionHandler
protected ResponseEntity<ErrorApiResponse> handleNotificationException(NotificationException exception) {
ErrorCode errorCode = exception.getErrorCode();
log.error("[handle NotificationException] - {}", exception.getMessage());

return new ResponseEntity<>(
ErrorApiResponse.of(errorCode, errorCode.getMessage()),
errorCode.getHttpStatus()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package site.packit.packit.domain.notification.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import site.packit.packit.domain.member.entity.Member;
import site.packit.packit.domain.notification.entity.PushNotificationSubscriber;

import java.util.Optional;

public interface PushNotificationSubscriberRepository extends JpaRepository<PushNotificationSubscriber, Long> {

Optional<PushNotificationSubscriber> findByMember(Member member);

boolean existsByMember(Member member);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package site.packit.packit.domain.notification.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.packit.packit.domain.member.entity.Member;
import site.packit.packit.domain.notification.entity.PushNotificationSubscriber;
import site.packit.packit.domain.notification.exception.NotificationException;
import site.packit.packit.domain.notification.repository.PushNotificationSubscriberRepository;

import static site.packit.packit.domain.notification.exception.NotificationErrorCode.PUSH_NOTIFICATION_SUBSCRIBER_ALREADY_EXIST;
import static site.packit.packit.domain.notification.exception.NotificationErrorCode.PUSH_NOTIFICATION_SUBSCRIBER_NOT_FOUND;

@Transactional
@Service
public class PushNotificationService {

private PushNotificationSubscriberRepository pushNotificationSubscriberRepository;

public PushNotificationService(PushNotificationSubscriberRepository pushNotificationSubscriberRepository) {
this.pushNotificationSubscriberRepository = pushNotificationSubscriberRepository;
}

public void createSubscriber(Member member) {
checkSubscriberExist(member);
pushNotificationSubscriberRepository.save(new PushNotificationSubscriber(member));
}

private void checkSubscriberExist(Member member) {
boolean isExist = isPushNotificationSubscriber(member);

if (isExist) {
throw new NotificationException(PUSH_NOTIFICATION_SUBSCRIBER_ALREADY_EXIST);
}
}

public void deleteSubscriber(Member member) {
PushNotificationSubscriber pushNotificationSubscriber = pushNotificationSubscriberRepository.findByMember(member)
.orElseThrow(() -> new NotificationException(PUSH_NOTIFICATION_SUBSCRIBER_NOT_FOUND));

pushNotificationSubscriberRepository.delete(pushNotificationSubscriber);
}

@Transactional(readOnly = true)
public boolean isPushNotificationSubscriber(Member member) {
return pushNotificationSubscriberRepository.existsByMember(member);
}
}

0 comments on commit c621b0d

Please sign in to comment.