#24 simple sns: 알림기능 api
This commit is contained in:
@@ -23,6 +23,8 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'com.vladmihalcea:hibernate-types-52:2.17.3'
|
||||
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@ package com.example.sns.controller;
|
||||
|
||||
import com.example.sns.controller.request.UserJoinRequest;
|
||||
import com.example.sns.controller.request.UserLoginRequest;
|
||||
import com.example.sns.controller.response.AlarmResponse;
|
||||
import com.example.sns.controller.response.Response;
|
||||
import com.example.sns.controller.response.UserJoinResponse;
|
||||
import com.example.sns.controller.response.UserLoginResponse;
|
||||
import com.example.sns.model.User;
|
||||
import com.example.sns.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/users")
|
||||
@@ -32,4 +33,9 @@ public class UserController {
|
||||
String token = userService.login(request.getName(), request.getPassword());
|
||||
return Response.success(new UserLoginResponse(token));
|
||||
}
|
||||
|
||||
@GetMapping("/alarm")
|
||||
public Response<Page<AlarmResponse>> alarm(Pageable pageable, Authentication authentication) {
|
||||
return Response.success(userService.alarmList(authentication.getName(), pageable).map(AlarmResponse::fromAlarm));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.example.sns.controller.response;
|
||||
|
||||
import com.example.sns.model.Alarm;
|
||||
import com.example.sns.model.AlarmArgs;
|
||||
import com.example.sns.model.AlarmType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AlarmResponse {
|
||||
|
||||
private Integer id;
|
||||
private AlarmType alarmType;
|
||||
private AlarmArgs args;
|
||||
private String text;
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updateAt;
|
||||
private Timestamp deleteAt;
|
||||
|
||||
public static AlarmResponse fromAlarm(Alarm alarm) {
|
||||
return new AlarmResponse(
|
||||
alarm.getId(),
|
||||
alarm.getAlarmType(),
|
||||
alarm.getArgs(),
|
||||
alarm.getAlarmType().getAlarmText(),
|
||||
alarm.getRegisteredAt(),
|
||||
alarm.getUpdatedAt(),
|
||||
alarm.getDeletedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
33
simple_sns/src/main/java/com/example/sns/model/Alarm.java
Normal file
33
simple_sns/src/main/java/com/example/sns/model/Alarm.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.example.sns.model;
|
||||
|
||||
import com.example.sns.model.entity.AlarmEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class Alarm {
|
||||
|
||||
private Integer id;
|
||||
private User user;
|
||||
private AlarmType alarmType;
|
||||
private AlarmArgs args;
|
||||
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updatedAt;
|
||||
private Timestamp deletedAt;
|
||||
|
||||
public static Alarm fromEntity(AlarmEntity entity) {
|
||||
return new Alarm(
|
||||
entity.getId(),
|
||||
User.fromEntity(entity.getUser()),
|
||||
entity.getAlarmType(),
|
||||
entity.getArgs(),
|
||||
entity.getRegisteredAt(),
|
||||
entity.getUpdatedAt(),
|
||||
entity.getDeletedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.example.sns.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AlarmArgs {
|
||||
|
||||
private Integer fromUserId;
|
||||
private Integer targetId;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.sns.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum AlarmType {
|
||||
NEW_COMMENT_ON_POST("new comment!"),
|
||||
NEW_LIKE_ON_POST("new like"),
|
||||
;
|
||||
|
||||
private final String alarmText;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.example.sns.model.entity;
|
||||
|
||||
import com.example.sns.model.AlarmArgs;
|
||||
import com.example.sns.model.AlarmType;
|
||||
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "alarms", indexes = {
|
||||
@Index(name = "user_id_idx", columnList = "user_id")
|
||||
})
|
||||
@Getter
|
||||
@Setter
|
||||
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
|
||||
@SQLDelete(sql = "UPDATE alarms SET deleted_at = NOW() where id=?")
|
||||
@Where(clause = "deleted_at IS NULL")
|
||||
public class AlarmEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private UserEntity user;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AlarmType alarmType;
|
||||
|
||||
@Type(type = "jsonb")
|
||||
@Column(columnDefinition = "json")
|
||||
private AlarmArgs args;
|
||||
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updatedAt;
|
||||
|
||||
@Column(name = "deleted_at")
|
||||
private Timestamp deletedAt;
|
||||
|
||||
@PrePersist
|
||||
void registeredAt() {
|
||||
this.registeredAt = Timestamp.from(Instant.now());
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
void updatedAt() {
|
||||
this.updatedAt = Timestamp.from(Instant.now());
|
||||
}
|
||||
|
||||
public static AlarmEntity of(UserEntity userEntity, AlarmType alarmType, AlarmArgs args) {
|
||||
AlarmEntity entity = new AlarmEntity();
|
||||
entity.setUser(userEntity);
|
||||
entity.setAlarmType(alarmType);
|
||||
entity.setArgs(args);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.sns.repository;
|
||||
|
||||
import com.example.sns.model.entity.AlarmEntity;
|
||||
import com.example.sns.model.entity.UserEntity;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AlarmEntityRepository extends JpaRepository<AlarmEntity, Integer> {
|
||||
|
||||
Page<AlarmEntity> findAllByUser(UserEntity user, Pageable pageable);
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
package com.example.sns.service;
|
||||
|
||||
import com.example.sns.exception.SnsApplicationException;
|
||||
import com.example.sns.model.AlarmArgs;
|
||||
import com.example.sns.model.AlarmType;
|
||||
import com.example.sns.model.Comment;
|
||||
import com.example.sns.model.Post;
|
||||
import com.example.sns.model.entity.CommentEntity;
|
||||
import com.example.sns.model.entity.LikeEntity;
|
||||
import com.example.sns.model.entity.PostEntity;
|
||||
import com.example.sns.model.entity.UserEntity;
|
||||
import com.example.sns.repository.CommentEntityRepository;
|
||||
import com.example.sns.repository.LikeEntityRepository;
|
||||
import com.example.sns.repository.PostEntityRepository;
|
||||
import com.example.sns.repository.UserEntityRepository;
|
||||
import com.example.sns.model.entity.*;
|
||||
import com.example.sns.repository.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -27,6 +23,7 @@ public class PostService {
|
||||
private final UserEntityRepository userEntityRepository;
|
||||
private final LikeEntityRepository likeEntityRepository;
|
||||
private final CommentEntityRepository commentEntityRepository;
|
||||
private final AlarmEntityRepository alarmEntityRepository;
|
||||
|
||||
@Transactional
|
||||
public void create(String title, String body, String username) {
|
||||
@@ -94,6 +91,13 @@ public class PostService {
|
||||
|
||||
// save like
|
||||
likeEntityRepository.save(LikeEntity.of(userEntity, postEntity));
|
||||
|
||||
alarmEntityRepository.save(AlarmEntity.of(
|
||||
postEntity.getUser(),
|
||||
AlarmType.NEW_LIKE_ON_POST,
|
||||
new AlarmArgs(userEntity.getId(), postEntity.getId())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public int likeCount(Integer postId) {
|
||||
@@ -109,6 +113,13 @@ public class PostService {
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
|
||||
commentEntityRepository.save(CommentEntity.of(userEntity, postEntity, comment));
|
||||
|
||||
alarmEntityRepository.save(AlarmEntity.of(
|
||||
postEntity.getUser(),
|
||||
AlarmType.NEW_COMMENT_ON_POST,
|
||||
new AlarmArgs(userEntity.getId(), postEntity.getId())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Page<Comment> getComments(Integer postId, Pageable pageable) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.example.sns.service;
|
||||
|
||||
import com.example.sns.exception.ErrorCode;
|
||||
import com.example.sns.exception.SnsApplicationException;
|
||||
import com.example.sns.model.Alarm;
|
||||
import com.example.sns.model.User;
|
||||
import com.example.sns.model.entity.UserEntity;
|
||||
import com.example.sns.repository.AlarmEntityRepository;
|
||||
import com.example.sns.repository.UserEntityRepository;
|
||||
import com.example.sns.util.JwtTokenUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -21,6 +22,7 @@ import static com.example.sns.exception.ErrorCode.*;
|
||||
public class UserService {
|
||||
|
||||
private final UserEntityRepository userEntityRepository;
|
||||
private final AlarmEntityRepository alarmEntityRepository;
|
||||
private final BCryptPasswordEncoder encoder;
|
||||
|
||||
@Value("${jwt.secret-key}")
|
||||
@@ -67,7 +69,12 @@ public class UserService {
|
||||
return JwtTokenUtils.generateToken(username, secretKey, expiredTimeMs);
|
||||
}
|
||||
|
||||
public Page<Void> alarmList(String username, Pageable pageable) {
|
||||
return Page.empty();
|
||||
public Page<Alarm> alarmList(String username, Pageable pageable) {
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(USER_NOT_FOUND, String.format("%s not founded", username))
|
||||
);
|
||||
|
||||
return alarmEntityRepository.findAllByUser(userEntity, pageable).map(Alarm::fromEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public class UserControllerTest {
|
||||
mockMvc.perform(get("/api/v1/users/alarm")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk());
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user