diff --git a/backend/src/main/java/online/wesal/wesal/controller/PostController.java b/backend/src/main/java/online/wesal/wesal/controller/PostController.java new file mode 100644 index 0000000..bed1765 --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/controller/PostController.java @@ -0,0 +1,61 @@ +package online.wesal.wesal.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import online.wesal.wesal.dto.ApiResponse; +import online.wesal.wesal.dto.PostCreateRequestDTO; +import online.wesal.wesal.dto.PostResponseDTO; +import online.wesal.wesal.entity.Post; +import online.wesal.wesal.service.PostService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/posts") +@CrossOrigin(origins = "*") +@Tag(name = "Posts", description = "Post management endpoints") +public class PostController { + + @Autowired + private PostService postService; + + @PostMapping(value = "/create", consumes = "application/json", produces = "application/json") + @Operation(summary = "Create post", description = "Create a new post") + public ResponseEntity> createPost( + @Valid @RequestBody PostCreateRequestDTO request, + BindingResult bindingResult, + Authentication authentication) { + + if (bindingResult.hasErrors()) { + String errorMessage = bindingResult.getFieldErrors().stream() + .map(error -> { + String field = error.getField(); + if ("body".equals(field)) return "Post body is required and cannot exceed 2000 characters"; + return error.getDefaultMessage(); + }) + .findFirst() + .orElse("Invalid input"); + return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage)); + } + + try { + Post post = postService.createPost(request.getBody()); + PostResponseDTO response = new PostResponseDTO(post); + return ResponseEntity.ok(ApiResponse.success(response)); + } catch (RuntimeException e) { + String message; + if (e.getMessage().contains("User not found")) { + message = "Authentication error. Please log in again."; + } else { + message = "Something went wrong.. We're sorry but try again later"; + } + return ResponseEntity.badRequest().body(ApiResponse.error(message)); + } catch (Exception e) { + return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later")); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/online/wesal/wesal/dto/PostCreateRequestDTO.java b/backend/src/main/java/online/wesal/wesal/dto/PostCreateRequestDTO.java new file mode 100644 index 0000000..cc1fa9c --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/dto/PostCreateRequestDTO.java @@ -0,0 +1,25 @@ +package online.wesal.wesal.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public class PostCreateRequestDTO { + + @NotBlank(message = "Post body cannot be empty") + @Size(max = 2000, message = "Post body cannot exceed 2000 characters") + private String body; + + public PostCreateRequestDTO() {} + + public PostCreateRequestDTO(String body) { + this.body = body; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} \ No newline at end of file diff --git a/backend/src/main/java/online/wesal/wesal/dto/PostResponseDTO.java b/backend/src/main/java/online/wesal/wesal/dto/PostResponseDTO.java new file mode 100644 index 0000000..0391268 --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/dto/PostResponseDTO.java @@ -0,0 +1,73 @@ +package online.wesal.wesal.dto; + +import online.wesal.wesal.entity.Post; +import java.time.LocalDateTime; + +public class PostResponseDTO { + + private String id; + private String creatorId; + private String body; + private String likes; + private String comments; + private LocalDateTime creationDate; + + public PostResponseDTO() {} + + public PostResponseDTO(Post post) { + this.id = String.valueOf(post.getId()); + this.creatorId = String.valueOf(post.getCreatorId()); + this.body = post.getBody(); + this.likes = String.valueOf(post.getLikes()); + this.comments = String.valueOf(post.getComments()); + this.creationDate = post.getCreationDate(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getCreatorId() { + return creatorId; + } + + public void setCreatorId(String creatorId) { + this.creatorId = creatorId; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getLikes() { + return likes; + } + + public void setLikes(String likes) { + this.likes = likes; + } + + public String getComments() { + return comments; + } + + public void setComments(String comments) { + this.comments = comments; + } + + public LocalDateTime getCreationDate() { + return creationDate; + } + + public void setCreationDate(LocalDateTime creationDate) { + this.creationDate = creationDate; + } +} \ No newline at end of file diff --git a/backend/src/main/java/online/wesal/wesal/entity/Post.java b/backend/src/main/java/online/wesal/wesal/entity/Post.java new file mode 100644 index 0000000..c6e7335 --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/entity/Post.java @@ -0,0 +1,85 @@ +package online.wesal.wesal.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +@Entity +@Table(name = "posts") +public class Post { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long creatorId; + + @Column(nullable = false, length = 2000) + @NotBlank + private String body; + + @Column(nullable = false) + private int likes = 0; + + @Column(nullable = false) + private int comments = 0; + + @Column(nullable = false) + private LocalDateTime creationDate = LocalDateTime.now(); + + public Post() {} + + public Post(Long creatorId, String body) { + this.creatorId = creatorId; + this.body = body; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCreatorId() { + return creatorId; + } + + public void setCreatorId(Long creatorId) { + this.creatorId = creatorId; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public int getLikes() { + return likes; + } + + public void setLikes(int likes) { + this.likes = likes; + } + + public int getComments() { + return comments; + } + + public void setComments(int comments) { + this.comments = comments; + } + + public LocalDateTime getCreationDate() { + return creationDate; + } + + public void setCreationDate(LocalDateTime creationDate) { + this.creationDate = creationDate; + } +} \ No newline at end of file diff --git a/backend/src/main/java/online/wesal/wesal/repository/PostRepository.java b/backend/src/main/java/online/wesal/wesal/repository/PostRepository.java new file mode 100644 index 0000000..867dc48 --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/repository/PostRepository.java @@ -0,0 +1,12 @@ +package online.wesal.wesal.repository; + +import online.wesal.wesal.entity.Post; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface PostRepository extends JpaRepository { + List findByCreatorIdOrderByCreationDateDesc(Long creatorId); +} \ No newline at end of file diff --git a/backend/src/main/java/online/wesal/wesal/service/PostService.java b/backend/src/main/java/online/wesal/wesal/service/PostService.java new file mode 100644 index 0000000..30796cb --- /dev/null +++ b/backend/src/main/java/online/wesal/wesal/service/PostService.java @@ -0,0 +1,23 @@ +package online.wesal.wesal.service; + +import online.wesal.wesal.entity.Post; +import online.wesal.wesal.entity.User; +import online.wesal.wesal.repository.PostRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class PostService { + + @Autowired + private PostRepository postRepository; + + @Autowired + private UserService userService; + + public Post createPost(String body) { + User currentUser = userService.getCurrentUser(); + Post post = new Post(currentUser.getId(), body); + return postRepository.save(post); + } +} \ No newline at end of file