#24 simple sns: 포스트 수정 api 구현
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
package com.example.sns.controller;
|
package com.example.sns.controller;
|
||||||
|
|
||||||
import com.example.sns.controller.request.PostCreateRequest;
|
import com.example.sns.controller.request.PostCreateRequest;
|
||||||
|
import com.example.sns.controller.request.PostModifyRequest;
|
||||||
|
import com.example.sns.controller.response.PostResponse;
|
||||||
import com.example.sns.controller.response.Response;
|
import com.example.sns.controller.response.Response;
|
||||||
|
import com.example.sns.model.Post;
|
||||||
import com.example.sns.service.PostService;
|
import com.example.sns.service.PostService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/posts")
|
@RequestMapping("/api/v1/posts")
|
||||||
@@ -25,4 +25,14 @@ public class PostController {
|
|||||||
|
|
||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{postId}")
|
||||||
|
public Response<PostResponse> modify(@RequestBody PostModifyRequest request,
|
||||||
|
@PathVariable Integer postId,
|
||||||
|
Authentication authentication) {
|
||||||
|
|
||||||
|
Post post = postService.modify(request.getTitle(), request.getBody(), authentication.getName(), postId);
|
||||||
|
|
||||||
|
return Response.success(PostResponse.fromPost(post));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.example.sns.controller.response;
|
||||||
|
|
||||||
|
import com.example.sns.model.Post;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PostResponse {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
private String title;
|
||||||
|
private String body;
|
||||||
|
private UserResponse user;
|
||||||
|
private Timestamp registeredAt;
|
||||||
|
private Timestamp updatedAt;
|
||||||
|
private Timestamp deletedAt;
|
||||||
|
|
||||||
|
public static PostResponse fromPost(Post post) {
|
||||||
|
return new PostResponse(
|
||||||
|
post.getId(),
|
||||||
|
post.getTitle(),
|
||||||
|
post.getBody(),
|
||||||
|
UserResponse.fromUser(post.getUser()),
|
||||||
|
post.getRegisteredAt(),
|
||||||
|
post.getUpdatedAt(),
|
||||||
|
post.getDeletedAt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.example.sns.controller.response;
|
||||||
|
|
||||||
|
import com.example.sns.model.User;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public
|
||||||
|
class UserResponse {
|
||||||
|
private Integer id;
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
public static UserResponse fromUser(User user) {
|
||||||
|
return new UserResponse(
|
||||||
|
user.getId(),
|
||||||
|
user.getUsername()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ public enum ErrorCode {
|
|||||||
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "User not founded."),
|
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "User not founded."),
|
||||||
INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, "Password is invalid."),
|
INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, "Password is invalid."),
|
||||||
INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "Token is invalid."),
|
INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "Token is invalid."),
|
||||||
POST_NOT_FOUND(HttpStatus.UNAUTHORIZED, "Post not founded."),
|
POST_NOT_FOUND(HttpStatus.NOT_FOUND, "Post not founded."),
|
||||||
INVALID_PERMISSION(HttpStatus.UNAUTHORIZED, "Permission is invalid."),
|
INVALID_PERMISSION(HttpStatus.UNAUTHORIZED, "Permission is invalid."),
|
||||||
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal server error.")
|
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal server error.")
|
||||||
|
|
||||||
|
|||||||
34
simple_sns/src/main/java/com/example/sns/model/Post.java
Normal file
34
simple_sns/src/main/java/com/example/sns/model/Post.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.example.sns.model;
|
||||||
|
|
||||||
|
import com.example.sns.model.entity.PostEntity;
|
||||||
|
import com.example.sns.model.entity.UserEntity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Post {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
private String title;
|
||||||
|
private String body;
|
||||||
|
private User user;
|
||||||
|
private Timestamp registeredAt;
|
||||||
|
private Timestamp updatedAt;
|
||||||
|
private Timestamp deletedAt;
|
||||||
|
|
||||||
|
public static Post fromEntity(PostEntity entity) {
|
||||||
|
return new Post(
|
||||||
|
entity.getId(),
|
||||||
|
entity.getTitle(),
|
||||||
|
entity.getBody(),
|
||||||
|
User.fromEntity(entity.getUser()),
|
||||||
|
entity.getRegisteredAt(),
|
||||||
|
entity.getUpdatedAt(),
|
||||||
|
entity.getDeletedAt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.example.sns.service;
|
package com.example.sns.service;
|
||||||
|
|
||||||
import com.example.sns.exception.ErrorCode;
|
|
||||||
import com.example.sns.exception.SnsApplicationException;
|
import com.example.sns.exception.SnsApplicationException;
|
||||||
|
import com.example.sns.model.Post;
|
||||||
import com.example.sns.model.entity.PostEntity;
|
import com.example.sns.model.entity.PostEntity;
|
||||||
import com.example.sns.model.entity.UserEntity;
|
import com.example.sns.model.entity.UserEntity;
|
||||||
import com.example.sns.repository.PostEntityRepository;
|
import com.example.sns.repository.PostEntityRepository;
|
||||||
@@ -10,6 +10,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import static com.example.sns.exception.ErrorCode.*;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PostService {
|
public class PostService {
|
||||||
@@ -22,7 +24,7 @@ public class PostService {
|
|||||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||||
.orElseThrow(
|
.orElseThrow(
|
||||||
() -> new SnsApplicationException(
|
() -> new SnsApplicationException(
|
||||||
ErrorCode.USER_NOT_FOUND,
|
USER_NOT_FOUND,
|
||||||
String.format("%s not founded", username)
|
String.format("%s not founded", username)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -31,18 +33,34 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void modify(String title, String body, String username, Integer postId) {
|
public Post modify(String title, String body, String username, Integer postId) {
|
||||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||||
.orElseThrow(
|
.orElseThrow(
|
||||||
() -> new SnsApplicationException(
|
() -> new SnsApplicationException(
|
||||||
ErrorCode.USER_NOT_FOUND,
|
USER_NOT_FOUND,
|
||||||
String.format("%s not founded", username)
|
String.format("%s not founded", username)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: post exist
|
PostEntity postEntity = postEntityRepository.findById(postId)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new SnsApplicationException(
|
||||||
|
POST_NOT_FOUND,
|
||||||
|
String.format("%s not founded", postId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: post permission
|
if (postEntity.getUser() != userEntity) {
|
||||||
|
throw new SnsApplicationException(
|
||||||
|
INVALID_PERMISSION,
|
||||||
|
String.format("%s has no permission with %s", username, postId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
postEntity.setTitle(title);
|
||||||
|
postEntity.setBody(body);
|
||||||
|
|
||||||
|
return Post.fromEntity(postEntityRepository.saveAndFlush(postEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import com.example.sns.controller.request.PostCreateRequest;
|
|||||||
import com.example.sns.controller.request.PostModifyRequest;
|
import com.example.sns.controller.request.PostModifyRequest;
|
||||||
import com.example.sns.exception.ErrorCode;
|
import com.example.sns.exception.ErrorCode;
|
||||||
import com.example.sns.exception.SnsApplicationException;
|
import com.example.sns.exception.SnsApplicationException;
|
||||||
|
import com.example.sns.fixture.PostEntityFixture;
|
||||||
|
import com.example.sns.model.Post;
|
||||||
import com.example.sns.service.PostService;
|
import com.example.sns.service.PostService;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -19,6 +21,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||||
@@ -72,6 +75,9 @@ public class PostControllerTest {
|
|||||||
String title = "title";
|
String title = "title";
|
||||||
String body = "body";
|
String body = "body";
|
||||||
|
|
||||||
|
when(postService.modify(eq(title), eq(body), any(), any()))
|
||||||
|
.thenReturn(Post.fromEntity(PostEntityFixture.get("username", 1, 1)));
|
||||||
|
|
||||||
mockMvc.perform(put("/api/v1/posts/1")
|
mockMvc.perform(put("/api/v1/posts/1")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsBytes(new PostModifyRequest(title, body)))
|
.content(objectMapper.writeValueAsBytes(new PostModifyRequest(title, body)))
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import com.example.sns.model.entity.UserEntity;
|
|||||||
|
|
||||||
public class PostEntityFixture {
|
public class PostEntityFixture {
|
||||||
|
|
||||||
public static PostEntity get(String username, Integer postId) {
|
public static PostEntity get(String username, Integer postId, Integer userId) {
|
||||||
UserEntity user = new UserEntity();
|
UserEntity user = new UserEntity();
|
||||||
user.setId(1);
|
user.setId(userId);
|
||||||
user.setUsername(username);
|
user.setUsername(username);
|
||||||
|
|
||||||
PostEntity result = new PostEntity();
|
PostEntity result = new PostEntity();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import com.example.sns.model.entity.UserEntity;
|
|||||||
|
|
||||||
public class UserEntityFixture {
|
public class UserEntityFixture {
|
||||||
|
|
||||||
public static UserEntity get(String username, String password) {
|
public static UserEntity get(String username, String password, Integer userId) {
|
||||||
UserEntity result = new UserEntity();
|
UserEntity result = new UserEntity();
|
||||||
result.setId(1);
|
result.setId(userId);
|
||||||
result.setUsername(username);
|
result.setUsername(username);
|
||||||
result.setPassword(password);
|
result.setPassword(password);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -68,11 +68,12 @@ public class PostServiceTest {
|
|||||||
String username = "username";
|
String username = "username";
|
||||||
Integer postId = 1;
|
Integer postId = 1;
|
||||||
|
|
||||||
PostEntity postEntity = PostEntityFixture.get(username, postId);
|
PostEntity postEntity = PostEntityFixture.get(username, postId, 1);
|
||||||
UserEntity userEntity = postEntity.getUser();
|
UserEntity userEntity = postEntity.getUser();
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(userEntity));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(userEntity));
|
||||||
when(postEntityRepository.findById(postId)).thenReturn(Optional.of(postEntity));
|
when(postEntityRepository.findById(postId)).thenReturn(Optional.of(postEntity));
|
||||||
|
when(postEntityRepository.saveAndFlush(any())).thenReturn(postEntity);
|
||||||
|
|
||||||
assertDoesNotThrow(() -> postService.modify(title, body, username, postId));
|
assertDoesNotThrow(() -> postService.modify(title, body, username, postId));
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,7 @@ public class PostServiceTest {
|
|||||||
String username = "username";
|
String username = "username";
|
||||||
Integer postId = 1;
|
Integer postId = 1;
|
||||||
|
|
||||||
PostEntity postEntity = PostEntityFixture.get(username, postId);
|
PostEntity postEntity = PostEntityFixture.get(username, postId, 1);
|
||||||
UserEntity userEntity = postEntity.getUser();
|
UserEntity userEntity = postEntity.getUser();
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(userEntity));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(userEntity));
|
||||||
@@ -103,8 +104,8 @@ public class PostServiceTest {
|
|||||||
String username = "username";
|
String username = "username";
|
||||||
Integer postId = 1;
|
Integer postId = 1;
|
||||||
|
|
||||||
PostEntity postEntity = PostEntityFixture.get(username, postId);
|
PostEntity postEntity = PostEntityFixture.get(username, postId, 1);
|
||||||
UserEntity writer = UserEntityFixture.get("username1", "password");
|
UserEntity writer = UserEntityFixture.get("username1", "password", 2);
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(writer));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(writer));
|
||||||
when(postEntityRepository.findById(postId)).thenReturn(Optional.of(postEntity));
|
when(postEntityRepository.findById(postId)).thenReturn(Optional.of(postEntity));
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class UserServiceTest {
|
|||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.empty());
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.empty());
|
||||||
when(encoder.encode(password)).thenReturn("encrypt_password");
|
when(encoder.encode(password)).thenReturn("encrypt_password");
|
||||||
when(userEntityRepository.save(any())).thenReturn(UserEntityFixture.get(username, password));
|
when(userEntityRepository.save(any())).thenReturn(UserEntityFixture.get(username, password, 1));
|
||||||
|
|
||||||
assertDoesNotThrow(() -> userService.join(username, password));
|
assertDoesNotThrow(() -> userService.join(username, password));
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ class UserServiceTest {
|
|||||||
String username = "username";
|
String username = "username";
|
||||||
String password = "password";
|
String password = "password";
|
||||||
|
|
||||||
UserEntity fixture = UserEntityFixture.get(username, password);
|
UserEntity fixture = UserEntityFixture.get(username, password, 1);
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
||||||
when(encoder.encode(password)).thenReturn("encrypt_password");
|
when(encoder.encode(password)).thenReturn("encrypt_password");
|
||||||
@@ -65,7 +65,7 @@ class UserServiceTest {
|
|||||||
String username = "username";
|
String username = "username";
|
||||||
String password = "password";
|
String password = "password";
|
||||||
|
|
||||||
UserEntity fixture = UserEntityFixture.get(username, password);
|
UserEntity fixture = UserEntityFixture.get(username, password, 1);
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
||||||
when(encoder.matches(password, fixture.getPassword())).thenReturn(true);
|
when(encoder.matches(password, fixture.getPassword())).thenReturn(true);
|
||||||
@@ -94,7 +94,7 @@ class UserServiceTest {
|
|||||||
String password = "password";
|
String password = "password";
|
||||||
String wrongPassword = "wrongPassword";
|
String wrongPassword = "wrongPassword";
|
||||||
|
|
||||||
UserEntity fixture = UserEntityFixture.get(username, password);
|
UserEntity fixture = UserEntityFixture.get(username, password, 1);
|
||||||
|
|
||||||
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
when(userEntityRepository.findByUsername(username)).thenReturn(Optional.of(fixture));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user