Added forum system
This commit is contained in:
1 parent
0d6fce8c48
commit
e49c871fd3
13 files changed
+303
-76
No files matched your search
@@ -60,4 +60,19 @@ public class User {
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
public boolean isModer() {
|
||||
if (roles.contains(Role.MODER) || roles.contains(Role.ADMIN)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
if (roles.contains(Role.ADMIN)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPremium() {
|
||||
if (roles.contains(Role.PREMIUM) || roles.contains(Role.ADMIN)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,19 @@ package site.easystartup.web.forum.controller;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import site.easystartup.web.domain.User;
|
||||
import site.easystartup.web.forum.domain.Discussion;
|
||||
import site.easystartup.web.forum.domain.DiscussionMessage;
|
||||
import site.easystartup.web.forum.domain.DiscussionStatus;
|
||||
import site.easystartup.web.forum.domain.Topic;
|
||||
import site.easystartup.web.forum.filter.ForumFilterService;
|
||||
import site.easystartup.web.forum.service.ForumService;
|
||||
import site.easystartup.web.forum.repo.TopicRepo;
|
||||
import site.easystartup.web.service.UserService;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@@ -22,7 +24,9 @@ import java.util.Date;
|
||||
public class ForumController {
|
||||
private final TopicRepo topicRepo;
|
||||
|
||||
private final ForumFilterService forumFilterService;
|
||||
private final ForumService forumService;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@GetMapping("/forum")
|
||||
public String forumMain(Model model) {
|
||||
@@ -33,8 +37,8 @@ public class ForumController {
|
||||
|
||||
@GetMapping("/forum/my")
|
||||
public String forumMy(Model model) {
|
||||
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
val discussions = forumFilterService.getDiscussionsByAuthor(user.getUsername());
|
||||
User user = userService.getCurrentUser();
|
||||
val discussions = forumService.getDiscussionsByAuthor(user.getUsername());
|
||||
model.addAttribute("discussions", discussions);
|
||||
return "/my-discussions";
|
||||
}
|
||||
@@ -44,37 +48,120 @@ public class ForumController {
|
||||
return "topic-new";
|
||||
}
|
||||
|
||||
@Secured({"ADMIN", "MODER"})
|
||||
@PostMapping("/forum/new")
|
||||
public String forumNewTopic(@RequestParam String title,
|
||||
@RequestParam String description) {
|
||||
description = description == null ? "" : description;
|
||||
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
Topic topic = new Topic();
|
||||
topic.setTitle(title);
|
||||
topic.setDescription(description);
|
||||
topic.setAuthor(user.getUsername());
|
||||
topic.setLast_update(new Date());
|
||||
topic.setSize(0);
|
||||
topicRepo.save(topic);
|
||||
forumService.createTopic(title, description, userService.getCurrentUser());
|
||||
return "/forum";
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/forum/{topic_id}")
|
||||
public String topicFirstPage(@PathVariable(value = "topic_id") long topic_id,
|
||||
Model model) {
|
||||
val pinned_discussions = forumFilterService.getPinnedDiscussionsByTopicId(topic_id);
|
||||
val pinned_discussions = forumService.getPinnedDiscussionsByTopicId(topic_id);
|
||||
model.addAttribute("pinned_discussions", pinned_discussions);
|
||||
val discussions = forumFilterService.getSortedDiscussionsByTopicId(topic_id).subList(0, 14);
|
||||
val discussions = forumService.getSortedDiscussionsByTopicId(topic_id).subList(0, 14);
|
||||
model.addAttribute("discussions", discussions);
|
||||
return "topic-first";
|
||||
return "/topic-first";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/{topic_id}/page/{page_index}")
|
||||
public String topicPage(@PathVariable(value = "topic_id") long topic_id,
|
||||
@PathVariable(value = "topic_id") long page_index,
|
||||
@PathVariable(value = "page_index") long page_index,
|
||||
Model model) {
|
||||
val discussions = forumFilterService.getSortedDiscussionsByTopicId(topic_id).subList((int)(15 * page_index), (int)(15 * page_index) + 15);
|
||||
val discussions = forumService.getSortedDiscussionsByTopicId(topic_id).subList((int)(15 * page_index), (int)(15 * page_index) + 15);
|
||||
model.addAttribute("discussions", discussions);
|
||||
return "topic-content";
|
||||
return "/topic-content";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/discussion/{discussion_id}")
|
||||
public String discussion(@PathVariable(value = "discussion_id") long discussion_id,
|
||||
Model model) {
|
||||
model.addAttribute("discussion", forumService.getDiscussionById(discussion_id));
|
||||
model.addAttribute("messages ", forumService.getMessagesByDiscussionId(discussion_id));
|
||||
return "/discussion";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/{topic_id}/create")
|
||||
public String discussionCreate(@PathVariable long topic_id) {
|
||||
return "/discussion-create";
|
||||
}
|
||||
|
||||
@PostMapping("/forum/{topic_id}/create")
|
||||
public String discussionCreatePost(@PathVariable long topic_id,
|
||||
@RequestParam String title) {
|
||||
forumService.createDiscussion(title, topic_id, userService.getCurrentUser());
|
||||
return "/discussion-create";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/discussion/{discussion_id}/edit")
|
||||
public String discussionEdit(@PathVariable long discussion_id, Model model) {
|
||||
Discussion discussion = forumService.getDiscussionById(discussion_id);
|
||||
User user = userService.getCurrentUser();
|
||||
if(!(discussion.getAuthor().equals(user.getUsername()) || user.isModer())) return "/403-error";
|
||||
model.addAttribute("discussion", discussion);
|
||||
return "/discussion-edit";
|
||||
}
|
||||
|
||||
@PostMapping("/forum/discussion/{discussion_id}/edit")
|
||||
public String discussionEditPost(@PathVariable long discussion_id,
|
||||
@RequestParam String title,
|
||||
@RequestParam DiscussionStatus status,
|
||||
Model model) {
|
||||
forumService.editDiscussion(title, discussion_id, status, userService.getCurrentUser());
|
||||
model.addAttribute("discussion", forumService.getDiscussionById(discussion_id));
|
||||
model.addAttribute("messages ", forumService.getMessagesByDiscussionId(discussion_id));
|
||||
return "/discussion";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/discussion/{discussion_id}/add")
|
||||
public String messageAdd(@PathVariable long discussion_id) {
|
||||
return "/discussion-message-add";
|
||||
}
|
||||
|
||||
@PostMapping("/forum/discussion/{discussion_id}/add")
|
||||
public String messageAddPost(@PathVariable long discussion_id,
|
||||
@RequestParam String text,
|
||||
Model model) {
|
||||
forumService.addDiscussionMessage(text, discussion_id, userService.getCurrentUser());
|
||||
model.addAttribute("discussion", forumService.getDiscussionById(discussion_id));
|
||||
model.addAttribute("messages ", forumService.getMessagesByDiscussionId(discussion_id));
|
||||
return "/discussion";
|
||||
}
|
||||
|
||||
@GetMapping("/forum/discussion/{discussion_id}/{message_id}/edit")
|
||||
public String messageEdit(@PathVariable long discussion_id,
|
||||
@PathVariable long message_id) {
|
||||
DiscussionMessage message = forumService.getDiscussionMessageById(message_id);
|
||||
User user = userService.getCurrentUser();
|
||||
if(!(message.getSender().equals(user.getUsername()) || user.isModer())) return "/403-error";
|
||||
return "/discussion-message-edit";
|
||||
}
|
||||
|
||||
@PostMapping("/forum/discussion/{discussion_id}/{message_id}/edit")
|
||||
public String messageEditPost(@PathVariable long discussion_id,
|
||||
@RequestParam String text,
|
||||
Model model, @PathVariable String message_id) {
|
||||
forumService.editDiscussionMessage(text, discussion_id, userService.getCurrentUser());
|
||||
model.addAttribute("discussion", forumService.getDiscussionById(discussion_id));
|
||||
model.addAttribute("messages ", forumService.getMessagesByDiscussionId(discussion_id));
|
||||
return "/discussion";
|
||||
}
|
||||
|
||||
@DeleteMapping("/forum/discussion/{discussion_id}/{message_id}/delete")
|
||||
public String messageDelete(@PathVariable long discussion_id,
|
||||
@PathVariable long message_id,
|
||||
Model model) {
|
||||
DiscussionMessage message = forumService.getDiscussionMessageById(message_id);
|
||||
User user = userService.getCurrentUser();
|
||||
if(!(message.getSender().equals(user.getUsername()) || user.isModer())) return "/403-error";
|
||||
|
||||
model.addAttribute("discussion", forumService.getDiscussionById(discussion_id));
|
||||
model.addAttribute("messages ", forumService.getMessagesByDiscussionId(discussion_id));
|
||||
return "/discussion";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class DiscussionMessage {
|
||||
private String sender;
|
||||
private Date date;
|
||||
private boolean edited;
|
||||
private long discussion_id;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package site.easystartup.web.forum.filter;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import site.easystartup.web.forum.domain.Discussion;
|
||||
import site.easystartup.web.forum.domain.DiscussionMessage;
|
||||
import site.easystartup.web.forum.repo.DiscussionMessageRepo;
|
||||
import site.easystartup.web.forum.repo.DiscussionRepo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class ForumFilterService {
|
||||
private final DiscussionMessageRepo discussionMessageRepo;
|
||||
|
||||
private final DiscussionRepo discussionRepo;
|
||||
|
||||
public List<DiscussionMessage> getMessagesByDiscussionId(long discussionId) {
|
||||
return Lists.newArrayList(discussionMessageRepo.findAll()).stream()
|
||||
.filter(m -> m.getId() == discussionId).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getDiscussionsByAuthor(String author) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> d.getAuthor().equals(author)).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getDiscussionsByMember(String member) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> getMessagesByDiscussionId(d.getId()).stream()
|
||||
.anyMatch(m -> m.getSender().equals(member))).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getPinnedDiscussionsByTopicId(long topic_id) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(Discussion::isPinned)
|
||||
.filter(d -> d.getTopic() == topic_id).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getSortedDiscussionsByTopicId(long topic_id) {
|
||||
List<Discussion> result = Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> !d.isPinned())
|
||||
.filter(d -> d.getTopic() == topic_id).toList();
|
||||
Collections.sort(result, Discussion::compareTo);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package site.easystartup.web.forum.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import site.easystartup.web.domain.Role;
|
||||
import site.easystartup.web.domain.User;
|
||||
import site.easystartup.web.forum.domain.Discussion;
|
||||
import site.easystartup.web.forum.domain.DiscussionMessage;
|
||||
import site.easystartup.web.forum.domain.DiscussionStatus;
|
||||
import site.easystartup.web.forum.domain.Topic;
|
||||
import site.easystartup.web.forum.repo.DiscussionMessageRepo;
|
||||
import site.easystartup.web.forum.repo.DiscussionRepo;
|
||||
import site.easystartup.web.forum.repo.TopicRepo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class ForumService {
|
||||
private final TopicRepo topicRepo;
|
||||
|
||||
private final DiscussionMessageRepo discussionMessageRepo;
|
||||
|
||||
private final DiscussionRepo discussionRepo;
|
||||
|
||||
public List<DiscussionMessage> getMessagesByDiscussionId(long discussionId) {
|
||||
return Lists.newArrayList(discussionMessageRepo.findAll()).stream()
|
||||
.filter(m -> m.getDiscussion_id() == discussionId).toList();
|
||||
}
|
||||
|
||||
public Discussion getDiscussionById(long discussionId) {
|
||||
return discussionRepo.findById(discussionId).get();
|
||||
}
|
||||
|
||||
public List<Discussion> getDiscussionsByAuthor(String author) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> d.getAuthor().equals(author)).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getDiscussionsByMember(String member) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> getMessagesByDiscussionId(d.getId()).stream()
|
||||
.anyMatch(m -> m.getSender().equals(member))).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getPinnedDiscussionsByTopicId(long topic_id) {
|
||||
return Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(Discussion::isPinned)
|
||||
.filter(d -> d.getTopic() == topic_id).toList();
|
||||
}
|
||||
|
||||
public List<Discussion> getSortedDiscussionsByTopicId(long topic_id) {
|
||||
List<Discussion> result = Lists.newArrayList(discussionRepo.findAll()).stream()
|
||||
.filter(d -> !d.isPinned())
|
||||
.filter(d -> d.getTopic() == topic_id).toList();
|
||||
Collections.sort(result, Discussion::compareTo);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void createTopic(String title, String description, User user) {
|
||||
description = description == null ? "" : description;
|
||||
Topic topic = new Topic();
|
||||
topic.setTitle(title);
|
||||
topic.setDescription(description);
|
||||
topic.setAuthor(user.getUsername());
|
||||
topic.setLast_update(new Date());
|
||||
topic.setSize(0);
|
||||
topicRepo.save(topic);
|
||||
}
|
||||
|
||||
public void createDiscussion(String title, long topic, User user) {
|
||||
Discussion discussion = new Discussion();
|
||||
discussion.setAuthor(user.getUsername());
|
||||
discussion.setDate(new Date());
|
||||
discussion.setTitle(title);
|
||||
discussion.setTopic(topic);
|
||||
discussion.setMessages(new ArrayList<>());
|
||||
discussion.setLast_update(new Date());
|
||||
discussion.setStatus(DiscussionStatus.OPEN);
|
||||
discussion.setPinned(false);
|
||||
discussionRepo.save(discussion);
|
||||
}
|
||||
|
||||
public void editDiscussion(String title, long discussion_id, DiscussionStatus status, User user) {
|
||||
Discussion discussion = discussionRepo.findById(discussion_id).orElseThrow();
|
||||
if(!(discussion.getAuthor().equals(user.getUsername()) || user.isModer())) throw new SecurityException();
|
||||
discussion.setAuthor(user.getUsername());
|
||||
discussion.setTitle(title);
|
||||
discussion.setLast_update(new Date());
|
||||
discussion.setStatus(status);
|
||||
discussionRepo.save(discussion);
|
||||
}
|
||||
|
||||
public void addDiscussionMessage(String text, long discussion_id, User user) {
|
||||
DiscussionMessage message = new DiscussionMessage();
|
||||
message.setDate(new Date());
|
||||
message.setEdited(false);
|
||||
message.setSender(user.getUsername());
|
||||
message.setText(text);
|
||||
message.setDiscussion_id(discussion_id);
|
||||
discussionMessageRepo.save(message);
|
||||
Discussion discussion = discussionRepo.findById(discussion_id).orElseThrow();
|
||||
List<Long> newMsgs = discussion.getMessages();
|
||||
newMsgs.add(message.getId());
|
||||
discussion.setMessages(newMsgs);
|
||||
discussionRepo.save(discussion);
|
||||
}
|
||||
|
||||
public void editDiscussionMessage(String text, long message_id, User user) {
|
||||
DiscussionMessage message = discussionMessageRepo.findById(message_id).orElseThrow();
|
||||
if(!(message.getSender().equals(user.getUsername()) || user.isAdmin())) throw new SecurityException();
|
||||
message.setEdited(true);
|
||||
message.setText(text);
|
||||
discussionMessageRepo.save(message);
|
||||
}
|
||||
|
||||
public void deleteDiscussionMessage(long message_id, User user) {
|
||||
DiscussionMessage message = discussionMessageRepo.findById(message_id).orElseThrow();
|
||||
if(!(message.getSender().equals(user.getUsername()) || user.isAdmin())) throw new SecurityException();
|
||||
discussionMessageRepo.delete(message);
|
||||
}
|
||||
|
||||
public DiscussionMessage getDiscussionMessageById(long id) {
|
||||
return discussionMessageRepo.findById(id).orElseThrow();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package site.easystartup.web.service;
|
||||
|
||||
public class UserNotAuthenticatedException extends RuntimeException {
|
||||
public UserNotAuthenticatedException() {
|
||||
super("The user is not logged in to the system!");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package site.easystartup.web.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.hibernate.query.criteria.internal.predicate.PredicateImplementor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import site.easystartup.web.domain.User;
|
||||
@@ -21,4 +22,12 @@ public class UserService {
|
||||
public User getUserById(Long userId) {
|
||||
return userRepo.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
}
|
||||
|
||||
public User getCurrentUser() {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if(auth.isAuthenticated()) throw new UserNotAuthenticatedException();
|
||||
org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User)
|
||||
auth.getPrincipal();
|
||||
return userRepo.findByUsername(user.getUsername());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>403</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>You have hot permissions for this!</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>403</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>403</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user