-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: Add CRUD posts API endpoints
Task: 86972yq1k
- Loading branch information
Showing
10 changed files
with
205 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 44 additions & 15 deletions
59
backend/src/main/java/meowhub/backend/posts/controllers/PostController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,83 @@ | ||
package meowhub.backend.posts.controllers; | ||
|
||
import jakarta.websocket.server.PathParam; | ||
import lombok.RequiredArgsConstructor; | ||
import meowhub.backend.posts.dtos.PostDto; | ||
import meowhub.backend.posts.services.PostService; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.PutMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.webjars.NotFoundException; | ||
|
||
@RestController | ||
@RequestMapping("api/posts") | ||
@RequiredArgsConstructor | ||
public class PostController { | ||
private final PostService postService; | ||
|
||
|
||
@GetMapping() | ||
public ResponseEntity<Page<PostDto>> getAllUsersPosts(@AuthenticationPrincipal UserDetails userDetails, @RequestParam(defaultValue = "0") int pageNo, @RequestParam(defaultValue = "10") int pageSize) { | ||
Page<PostDto> posts = postService.getAllPosts(userDetails.getUsername(), pageNo, pageSize); | ||
public ResponseEntity<Page<PostDto>> getPosts(@AuthenticationPrincipal UserDetails userDetails, @RequestParam(defaultValue = "0") int pageNo, @RequestParam(defaultValue = "10") int pageSize) { | ||
Page<PostDto> posts = postService.getPosts(userDetails.getUsername(), pageNo, pageSize); | ||
return ResponseEntity.ok(posts); | ||
} | ||
|
||
@GetMapping("/{login}") | ||
public ResponseEntity<Page<PostDto>> getPostsForUser(@PathParam("login") String login, @AuthenticationPrincipal UserDetails userDetails, @RequestParam(defaultValue = "0") int pageNo, @RequestParam(defaultValue = "10") int pageSize) { | ||
Page<PostDto> posts = postService.getAllPostsForUser(login, userDetails.getUsername(), pageNo, pageSize); | ||
return ResponseEntity.ok(posts); | ||
public ResponseEntity<Page<PostDto>> getPostsForUser(@PathVariable("login") String login, @AuthenticationPrincipal UserDetails userDetails, @RequestParam(defaultValue = "0") int pageNo, @RequestParam(defaultValue = "10") int pageSize) { | ||
try { | ||
Page<PostDto> posts = postService.getPostsForUser(login, userDetails.getUsername(), pageNo, pageSize); | ||
return ResponseEntity.ok(posts); | ||
} catch (UsernameNotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested user not found").build(); | ||
} | ||
} | ||
|
||
@PostMapping("") | ||
public ResponseEntity<PostDto> createPost(@RequestParam String content, @AuthenticationPrincipal UserDetails userDetails) { | ||
PostDto postDto = postService.createPost(userDetails.getUsername(), content); | ||
return ResponseEntity.ok(postDto); | ||
try { | ||
PostDto postDto = postService.createPost(userDetails.getUsername(), content); | ||
return ResponseEntity.ok(postDto); | ||
} catch (UsernameNotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested user not found").build(); | ||
} | ||
} | ||
|
||
@DeleteMapping("/{postId}") | ||
public ResponseEntity<Void> deletePost(@PathParam("postId") String postId, @AuthenticationPrincipal UserDetails userDetails) { | ||
postService.deletePost(userDetails.getUsername(), postId); | ||
return ResponseEntity.ok().build(); | ||
public ResponseEntity<Void> deletePost(@PathVariable("postId") String postId, @AuthenticationPrincipal UserDetails userDetails) { | ||
try { | ||
postService.deletePost(userDetails.getUsername(), postId); | ||
return ResponseEntity.ok().build(); | ||
} catch (UsernameNotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested user not found").build(); | ||
} catch (NotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested post not found").build(); | ||
} | ||
} | ||
|
||
@PutMapping("/{postId}") | ||
public ResponseEntity<PostDto> updatePost(@PathParam("postId") String postId, @RequestParam String content, @AuthenticationPrincipal UserDetails userDetails) { | ||
PostDto postDto = postService.updatePost(userDetails.getUsername(), postId, content); | ||
return ResponseEntity.ok(postDto); | ||
public ResponseEntity<PostDto> updatePost(@PathVariable("postId") String postId, @RequestParam String content, @AuthenticationPrincipal UserDetails userDetails) { | ||
try { | ||
PostDto postDto = postService.updatePost(userDetails.getUsername(), postId, content); | ||
return ResponseEntity.ok(postDto); | ||
} catch (UsernameNotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested user not found").build(); | ||
} catch (NotFoundException exception) { | ||
exception.printStackTrace(); | ||
return ResponseEntity.notFound().eTag("Requested post not found").build(); | ||
} | ||
} | ||
} | ||
} |
10 changes: 6 additions & 4 deletions
10
backend/src/main/java/meowhub/backend/posts/dtos/PostDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,19 @@ | ||
package meowhub.backend.posts.dtos; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import meowhub.backend.users.dtos.BasicUserInfoDto; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
import java.time.LocalDateTime; | ||
|
||
@Builder | ||
@Data | ||
@AllArgsConstructor | ||
public class PostDto { | ||
private String id; | ||
private String content; | ||
private BasicUserInfoDto author; | ||
private List<CommentDto> comments; | ||
private LocalDate createdAt; | ||
private Long numberOfComments; | ||
private LocalDateTime createdAt; | ||
} |
137 changes: 97 additions & 40 deletions
137
backend/src/main/java/meowhub/backend/posts/repositories/PostRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,118 @@ | ||
package meowhub.backend.posts.repositories; | ||
|
||
import meowhub.backend.posts.dtos.PostDto; | ||
import meowhub.backend.posts.models.Post; | ||
import meowhub.backend.users.models.User; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface PostRepository extends JpaRepository<Post, String> { | ||
Page<Post> findAllByUserLogin(String login, Pageable pageable); | ||
Optional<Post> findByUserLoginAndId(String login, String id); | ||
|
||
@Query(value = """ | ||
SELECT new meowhub.backend.posts.dtos.PostDto ( | ||
p.id, | ||
p.contentHtml, | ||
new meowhub.backend.users.dtos.BasicUserInfoDto ( | ||
u.id, | ||
u.name, | ||
u.surname, | ||
u.login, | ||
pictures.picture | ||
), | ||
(SELECT COUNT(c.id) FROM Comment c WHERE c.post.id = p.id), | ||
p.createdAt | ||
) | ||
FROM User u | ||
JOIN u.posts p | ||
LEFT JOIN Picture pictures ON pictures.user.id = u.id | ||
LEFT JOIN ProfilePicture pp ON pp.picture.id = pictures.id | ||
LEFT JOIN u.postsPrivacy postsPrivacy | ||
WHERE postsPrivacy.code = 'PUBLIC' | ||
OR (postsPrivacy.code = 'FRIENDS_ONLY' AND u.id IN (u.id, | ||
(SELECT r.receiver.id | ||
FROM User sender | ||
JOIN sender.userRelationsSender r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND sender.login = :requestedBy | ||
UNION | ||
SELECT r.sender.id | ||
FROM User receiver | ||
JOIN receiver.userRelationsReceiver r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND receiver.login = :requestedBy | ||
))) | ||
""") | ||
Page<PostDto> findIfPublicOrFriends(@Param("requestedBy") String requestedBy, Pageable pageable); | ||
|
||
@Query(""" | ||
SELECT p | ||
FROM User u | ||
JOIN u.posts p | ||
LEFT JOIN u.postsPrivacy postsPrivacy | ||
WHERE u.login = :login | ||
AND (postsPrivacy.code = 'PUBLIC' | ||
OR (postsPrivacy.code = 'FRIENDS' AND u.id IN ( | ||
SELECT r.receiver.id | ||
FROM User sender | ||
JOIN sender.userRelationsSender r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND sender.login = :requestedBy | ||
UNION | ||
SELECT r.sender.id | ||
FROM User receiver | ||
JOIN receiver.userRelationsReceiver r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND receiver.login = :requestedBy | ||
))) | ||
""") | ||
Page<Post> findAllByUserLoginIfPublicOrFriend(@Param("login") String login, @Param("requestedBy") String requestedBy, Pageable pageable); | ||
SELECT new meowhub.backend.posts.dtos.PostDto ( | ||
p.id, | ||
p.contentHtml, | ||
new meowhub.backend.users.dtos.BasicUserInfoDto ( | ||
u.id, | ||
u.name, | ||
u.surname, | ||
u.login, | ||
pictures.picture | ||
), | ||
(SELECT COUNT(c.id) FROM Comment c WHERE c.post.id = p.id), | ||
p.createdAt | ||
) | ||
FROM User u | ||
JOIN u.posts p | ||
LEFT JOIN Picture pictures ON pictures.user.id = u.id | ||
LEFT JOIN ProfilePicture pp ON pp.picture.id = pictures.id | ||
LEFT JOIN u.postsPrivacy postsPrivacy | ||
WHERE u.login = :login | ||
AND (postsPrivacy.code = 'PUBLIC' | ||
OR (postsPrivacy.code = 'FRIENDS_ONLY' AND u.id IN ( | ||
SELECT r.receiver.id | ||
FROM User sender | ||
JOIN sender.userRelationsSender r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND sender.login = :requestedBy | ||
UNION | ||
SELECT r.sender.id | ||
FROM User receiver | ||
JOIN receiver.userRelationsReceiver r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND receiver.login = :requestedBy) | ||
)) ORDER BY p.createdAt DESC | ||
""") | ||
Page<PostDto> findByUserLoginIfPublicOrFriend(@Param("login") String login, @Param("requestedBy") String requestedBy, Pageable pageable); | ||
|
||
@Query(""" | ||
SELECT r.receiver.id | ||
FROM User sender | ||
JOIN sender.userRelationsSender r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND sender.login = :login | ||
UNION | ||
SELECT r.sender.id | ||
FROM User receiver | ||
JOIN receiver.userRelationsReceiver r | ||
JOIN r.relationType relType | ||
WHERE relType.code = 'FRIENDS' | ||
AND receiver.login = :login | ||
SELECT new meowhub.backend.posts.dtos.PostDto ( | ||
p.id, | ||
p.contentHtml, | ||
new meowhub.backend.users.dtos.BasicUserInfoDto ( | ||
u.id, | ||
u.name, | ||
u.surname, | ||
u.login, | ||
pictures.picture | ||
), | ||
(SELECT COUNT(c.id) FROM Comment c WHERE c.post.id = p.id), | ||
p.createdAt | ||
) | ||
FROM User u | ||
JOIN u.posts p | ||
LEFT JOIN Picture pictures ON pictures.user.id = u.id | ||
LEFT JOIN ProfilePicture pp ON pp.picture.id = pictures.id | ||
LEFT JOIN u.postsPrivacy postsPrivacy | ||
WHERE u.login = :login | ||
ORDER BY p.createdAt DESC | ||
""") | ||
List<User> findFriendsByLogin(@Param("login") String login); | ||
Page<PostDto> findOwn(@Param("login") String login, Pageable pageable); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.