From db572e6f2b50a6253d01b33b04ed717fddc7b46b Mon Sep 17 00:00:00 2001 From: _Bastler Date: Thu, 7 Oct 2021 14:00:40 +0200 Subject: [PATCH] flagging --- pom.xml | 2 +- .../board/businesslogic/CommentManager.java | 85 ++++--- .../board/businesslogic/EntryManager.java | 40 +++- .../board/businesslogic/FlagManager.java | 219 ++++++++++++++++++ .../board/businesslogic/SettingsManager.java | 11 + .../board/businesslogic/UserManager.java | 66 ++++++ .../board/businesslogic/VoteManager.java | 4 +- .../board/controller/CommentController.java | 40 ++-- .../board/controller/EntryController.java | 42 ++-- .../board/controller/FlagController.java | 132 +++++++++++ .../controller/ModerationController.java | 102 +++++++- .../board/controller/VoteController.java | 12 +- .../java/de/bstly/board/model/Comment.java | 23 ++ src/main/java/de/bstly/board/model/Entry.java | 41 ++-- .../de/bstly/board/model/EntryStatus.java | 8 +- .../java/de/bstly/board/model/EntryType.java | 10 +- src/main/java/de/bstly/board/model/Flag.java | 107 +++++++++ .../de/bstly/board/model/FlaggedStatus.java | 12 + .../java/de/bstly/board/model/LocalUser.java | 20 -- .../de/bstly/board/model/PersistentLogin.java | 8 - src/main/java/de/bstly/board/model/Types.java | 8 +- src/main/java/de/bstly/board/model/Vote.java | 9 - .../java/de/bstly/board/model/VoteType.java | 9 +- .../board/repository/CommentRepository.java | 114 +++++---- .../board/repository/EntryRepository.java | 32 +-- .../board/repository/FlagRepository.java | 18 ++ src/main/resources/messages.properties | 46 ---- 27 files changed, 916 insertions(+), 304 deletions(-) create mode 100644 src/main/java/de/bstly/board/businesslogic/FlagManager.java create mode 100644 src/main/java/de/bstly/board/controller/FlagController.java create mode 100644 src/main/java/de/bstly/board/model/Flag.java create mode 100644 src/main/java/de/bstly/board/model/FlaggedStatus.java create mode 100644 src/main/java/de/bstly/board/repository/FlagRepository.java delete mode 100644 src/main/resources/messages.properties diff --git a/pom.xml b/pom.xml index 99f8f4a..599c97c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ UTF-8 11 - 0.4.3-SNAPSHOT + 0.5.0-SNAPSHOT diff --git a/src/main/java/de/bstly/board/businesslogic/CommentManager.java b/src/main/java/de/bstly/board/businesslogic/CommentManager.java index 9e40d5a..5a86686 100644 --- a/src/main/java/de/bstly/board/businesslogic/CommentManager.java +++ b/src/main/java/de/bstly/board/businesslogic/CommentManager.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; import com.querydsl.jpa.impl.JPAQueryFactory; import de.bstly.board.model.Comment; +import de.bstly.board.model.FlaggedStatus; import de.bstly.board.model.QComment; import de.bstly.board.model.QEntry; import de.bstly.board.model.QVote; @@ -38,6 +39,9 @@ public class CommentManager { private VoteRepository voteRepository; @Autowired private VoteManager voteManager; + @Autowired + private FlagManager flagManager; + private QComment qComment = QComment.comment; private QVote qVote = QVote.vote; private QEntry qEntry = QEntry.entry; @@ -46,45 +50,62 @@ public class CommentManager { * Fetch by date. * * @param username the username - * @param target the target - * @param parent the parent - * @param date the date - * @param page the page - * @param size the size - * @param desc the desc + * @param target the target + * @param parent the parent + * @param date the date + * @param page the page + * @param size the size + * @param desc the desc * @return the page */ public Page fetchByDate(String username, Long target, Long parent, Instant date, int page, int size, boolean desc) { Sort sort = Sort.by(desc ? Order.desc("created") : Order.asc("created")); if (parent == null) { - return commentRepository.findAll( - qComment.target.eq(target).and(qComment.parent.isNull()) - .and(qComment.created.before(date).or(qComment.author.eq(username))), - PageRequest.of(page, size, sort)); + return commentRepository + .findAll( + qComment.target.eq(target).and(qComment.parent.isNull()) + .and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)) + .and(qComment.created.before(date) + .or(qComment.author.eq(username))), + PageRequest.of(page, size, sort)); } return commentRepository.findAll(qComment.target.eq(target).and(qComment.parent.eq(parent)) + .and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)) .and(qComment.created.before(date)), PageRequest.of(page, size, sort)); } + /** + * Fetch flagged. + * + * @param page the page + * @param size the size + * @param asc the asc + * @return the page + */ + public Page fetchFlagged(int page, int size, boolean asc) { + Sort sort = Sort.by(asc ? Order.asc("created") : Order.desc("created")); + return commentRepository.findAll(qComment.flaggedStatus.eq(FlaggedStatus.FLAGGED), + PageRequest.of(page, size, sort)); + } + /** * Fetch by username. * * @param username the username - * @param orElse the or else - * @param date the date - * @param page the page - * @param size the size - * @param asc the asc + * @param date the date + * @param page the page + * @param size the size + * @param asc the asc * @return the page */ - public Page fetchByUsername(String username, Long orElse, Instant date, int page, - int size, boolean asc) { + public Page fetchByUsername(String username, Instant date, int page, int size, + boolean asc) { Sort sort = Sort.by(asc ? Order.asc("created") : Order.desc("created")); - return commentRepository.findAll( - qComment.author.equalsIgnoreCase(username).and(qComment.created.before(date)), - PageRequest.of(page, size, sort)); + return commentRepository.findAll(qComment.author.equalsIgnoreCase(username) + .and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)) + .and(qComment.created.before(date)), PageRequest.of(page, size, sort)); } /** @@ -100,6 +121,7 @@ public class CommentManager { } return commentRepository.count(qComment.target.eq(target).and(qComment.parent.eq(parent)) + .and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)) .and(qComment.created.before(Instant.now()))); } @@ -110,16 +132,17 @@ public class CommentManager { * @return the long */ public Long count(Long target) { - return commentRepository - .count(qComment.target.eq(target).and(qComment.created.before(Instant.now()))); + return commentRepository.count( + qComment.target.eq(target).and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)) + .and(qComment.created.before(Instant.now()))); } /** * Apply metadata. * * @param username the username - * @param comment the comment - * @param ignore the ignore + * @param comment the comment + * @param ignore the ignore */ public void applyMetadata(String username, Comment comment, List ignore) { @@ -160,6 +183,16 @@ public class CommentManager { .and(qVote.author.equalsIgnoreCase(username)))); } + if (!username.equals(comment.getAuthor()) && !ignore.contains("flag")) { + comment.getMetadata().put("flag", + flagManager.get(username, comment.getId(), Types.comment) == null); + } + + if (!username.equals(comment.getAuthor()) && !ignore.contains("unflag")) { + comment.getMetadata().put("unflag", + flagManager.get(username, comment.getId(), Types.comment) != null); + } + if (!ignore.contains("entry")) { comment.getMetadata().put("entry", jpaQueryFactory.selectFrom(qEntry) .where(qEntry.id.eq(comment.getTarget())).select(qEntry.title).fetchOne()); @@ -170,8 +203,8 @@ public class CommentManager { * Apply metadata. * * @param username the username - * @param entries the entries - * @param ignore the ignore + * @param entries the entries + * @param ignore the ignore */ public void applyMetadata(String username, List entries, List ignore) { for (Comment comment : entries) { diff --git a/src/main/java/de/bstly/board/businesslogic/EntryManager.java b/src/main/java/de/bstly/board/businesslogic/EntryManager.java index 82ae37d..f78ca70 100644 --- a/src/main/java/de/bstly/board/businesslogic/EntryManager.java +++ b/src/main/java/de/bstly/board/businesslogic/EntryManager.java @@ -17,6 +17,8 @@ import com.google.common.collect.Lists; import de.bstly.board.model.Bookmarks; import de.bstly.board.model.Entry; +import de.bstly.board.model.EntryStatus; +import de.bstly.board.model.FlaggedStatus; import de.bstly.board.model.QEntry; import de.bstly.board.model.QVote; import de.bstly.board.model.RankedEntry; @@ -43,6 +45,8 @@ public class EntryManager { private BookmarksManager bookmarksManager; @Autowired private SettingsManager settingsManager; + @Autowired + private FlagManager flagManager; private QEntry qEntry = QEntry.entry; @@ -95,10 +99,25 @@ public class EntryManager { * @return the page */ public Page fetchByDate(Instant date, int page, int size) { - return entryRepository.findAll(qEntry.created.before(date), + return entryRepository.findAll( + qEntry.created.before(date).and(qEntry.entryStatus.eq(EntryStatus.NORMAL)), PageRequest.of(page, size, Sort.by(Order.desc("created")))); } + /** + * Fetch flagged. + * + * @param page the page + * @param size the size + * @param asc the asc + * @return the page + */ + public Page fetchFlagged(int page, int size, boolean asc) { + Sort sort = Sort.by(asc ? Order.asc("created") : Order.desc("created")); + return entryRepository.findAll(qEntry.flaggedStatus.ne(FlaggedStatus.NORMAL), + PageRequest.of(page, size, sort)); + } + /** * Fetch by user. * @@ -155,8 +174,13 @@ public class EntryManager { entry.getMetadata().put("points", voteManager.getPoints(entry.getId(), Types.entry)); } - if (!ignore.contains("bookmarked")) { - entry.getMetadata().put("bookmarked", + if (!ignore.contains("bookmark")) { + entry.getMetadata().put("bookmark", + !bookmarksManager.hasEntry(username, entry.getId())); + } + + if (!ignore.contains("removeBookmark")) { + entry.getMetadata().put("removeBookmark", bookmarksManager.hasEntry(username, entry.getId())); } @@ -174,6 +198,16 @@ public class EntryManager { .and(qVote.author.equalsIgnoreCase(username)))); } + if (!username.equals(entry.getAuthor()) && !ignore.contains("flag")) { + entry.getMetadata().put("flag", + flagManager.get(username, entry.getId(), Types.entry) == null); + } + + if (!username.equals(entry.getAuthor()) && !ignore.contains("unflag")) { + entry.getMetadata().put("unflag", + flagManager.get(username, entry.getId(), Types.entry) != null); + } + if (voteRepository .exists(qVote.target.eq(entry.getId()).and(qVote.targetType.eq(Types.entry)) .and(qVote.author.equalsIgnoreCase(username)))) { diff --git a/src/main/java/de/bstly/board/businesslogic/FlagManager.java b/src/main/java/de/bstly/board/businesslogic/FlagManager.java new file mode 100644 index 0000000..13555e4 --- /dev/null +++ b/src/main/java/de/bstly/board/businesslogic/FlagManager.java @@ -0,0 +1,219 @@ +/** + * + */ +package de.bstly.board.businesslogic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import de.bstly.board.model.Comment; +import de.bstly.board.model.Entry; +import de.bstly.board.model.Flag; +import de.bstly.board.model.FlaggedStatus; +import de.bstly.board.model.QComment; +import de.bstly.board.model.QFlag; +import de.bstly.board.model.Types; +import de.bstly.board.repository.CommentRepository; +import de.bstly.board.repository.FlagRepository; + +/** + * The Class FlagManager. + */ +@Component +public class FlagManager { + + @Autowired + private FlagRepository flagRepository; + @Autowired + private SettingsManager settingsManager; + @Autowired + private EntryManager entryManager; + @Autowired + private CommentManager commentManager; + @Autowired + private CommentRepository commentRepository; + + private QFlag qFlag = QFlag.flag; + private QComment qComment = QComment.comment; + + /** + * Gets the. + * + * @param author the author + * @param target the target + * @param targetType the target type + * @return the flag + */ + public Flag get(String author, Long target, Types targetType) { + return flagRepository.findOne(qFlag.author.eq(author).and(qFlag.targetType.eq(targetType)) + .and(qFlag.target.eq(target))).orElse(null); + } + + /** + * Save. + * + * @param flag the flag + * @return the flag + */ + public Flag save(Flag flag) { + return flagRepository.save(flag); + } + + /** + * Delete. + * + * @param flag the flag + */ + public void delete(Flag flag) { + flagRepository.delete(flag); + } + + /** + * Delete by target. + * + * @param target the target + * @param targetType the target type + */ + public void deleteByTarget(Long target, Types targetType) { + for (Flag flag : flagRepository + .findAll(qFlag.target.eq(target).and(qFlag.targetType.eq(targetType)))) { + delete(flag); + } + } + + /** + * Gets the flags. + * + * @param target the target + * @param targetType the target type + * @return the flags + */ + public long getFlags(Long target, Types targetType) { + return flagRepository.count(qFlag.target.eq(target).and(qFlag.targetType.eq(targetType))); + } + + /** + * Check flag status. + * + * @param target the target + * @param targetType the target type + */ + public void checkFlagStatus(Long target, Types targetType) { + switch (targetType) { + case comment: + checkCommentFlagStatus(target); + break; + case entry: + checkEntryFlagStatus(target); + break; + case user: + break; + default: + break; + } + } + + /** + * Check comment flag status. + * + * @param target the target + */ + public void checkCommentFlagStatus(Long target) { + Assert.isTrue(commentManager.exists(target), "Comment not exists: '" + + target + + "'!"); + Comment comment = commentManager.get(target); + + if (getFlags(target, Types.comment) >= settingsManager.getFlahThresh()) { + if (!FlaggedStatus.FLAGGED.equals(comment.getFlaggedStatus())) { + flagComment(comment); + } + } else if (FlaggedStatus.FLAGGED.equals(comment.getFlaggedStatus())) { + unflagComment(comment); + } + } + + /** + * Flag comment. + * + * @param comment the comment + */ + protected void flagComment(Comment comment) { + comment.setFlaggedStatus(FlaggedStatus.FLAGGED); + comment = commentManager.save(comment); + hideSubcomments(comment); + } + + /** + * Hide subcomments. + * + * @param comment the comment + */ + protected void hideSubcomments(Comment comment) { + for (Comment subcomment : commentRepository.findAll(qComment.parent.eq(comment.getId()) + .and(qComment.flaggedStatus.eq(FlaggedStatus.NORMAL)))) { + subcomment.setFlaggedStatus(FlaggedStatus.HIDDEN); + subcomment = commentManager.save(subcomment); + hideSubcomments(subcomment); + } + } + + /** + * Unflag comment. + * + * @param comment the comment + */ + protected void unflagComment(Comment comment) { + comment.setFlaggedStatus(FlaggedStatus.NORMAL); + comment = commentManager.save(comment); + unhideSubcomments(comment); + } + + /** + * Unhide subcomments. + * + * @param comment the comment + */ + protected void unhideSubcomments(Comment comment) { + for (Comment subcomment : commentRepository.findAll(qComment.parent.eq(comment.getId()) + .and(qComment.flaggedStatus.eq(FlaggedStatus.HIDDEN)))) { + subcomment.setFlaggedStatus(FlaggedStatus.NORMAL); + subcomment = commentManager.save(subcomment); + hideSubcomments(subcomment); + } + } + + /** + * Check entry flag status. + * + * @param target the target + */ + public void checkEntryFlagStatus(Long target) { + Assert.isTrue(entryManager.exists(target), "Entry not exists: '" + + target + + "'!"); + Entry entry = entryManager.get(target); + if (getFlags(target, Types.entry) >= settingsManager.getFlahThresh()) { + if (!FlaggedStatus.FLAGGED.equals(entry.getFlaggedStatus())) { + entry.setFlaggedStatus(FlaggedStatus.FLAGGED); + entryManager.save(entry); + } + } else if (FlaggedStatus.FLAGGED.equals(entry.getFlaggedStatus())) { + entry.setFlaggedStatus(FlaggedStatus.NORMAL); + entryManager.save(entry); + } + } + + /** + * Unflag. + * + * @param target the target + * @param targetType the target type + */ + public void unflag(Long target, Types targetType) { + deleteByTarget(target, targetType); + checkFlagStatus(target, targetType); + } + +} diff --git a/src/main/java/de/bstly/board/businesslogic/SettingsManager.java b/src/main/java/de/bstly/board/businesslogic/SettingsManager.java index 8d22785..0c7f838 100644 --- a/src/main/java/de/bstly/board/businesslogic/SettingsManager.java +++ b/src/main/java/de/bstly/board/businesslogic/SettingsManager.java @@ -20,6 +20,8 @@ public class SettingsManager { private long COMMENT_CHANGE_PERIDO; @Value("${bstly.board.unvoteThresh:10}") private long UNVOTE_THRESH; + @Value("${bstly.board.flagThresh:3}") + private long FLAG_THRESH; /** * Gets the gravity. @@ -56,4 +58,13 @@ public class SettingsManager { public long getUnvoteThresh() { return UNVOTE_THRESH; } + + /** + * Gets the flah thresh. + * + * @return the flah thresh + */ + public long getFlahThresh() { + return FLAG_THRESH; + } } diff --git a/src/main/java/de/bstly/board/businesslogic/UserManager.java b/src/main/java/de/bstly/board/businesslogic/UserManager.java index 943aff4..8e5996c 100644 --- a/src/main/java/de/bstly/board/businesslogic/UserManager.java +++ b/src/main/java/de/bstly/board/businesslogic/UserManager.java @@ -71,6 +71,39 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet /* * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ /* * @see org.springframework.security.core.userdetails.UserDetailsService# * loadUserByUsername(java.lang.String) @@ -116,6 +149,39 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet /* * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ /* * @see org.springframework.beans.factory.SmartInitializingSingleton# * afterSingletonsInstantiated() diff --git a/src/main/java/de/bstly/board/businesslogic/VoteManager.java b/src/main/java/de/bstly/board/businesslogic/VoteManager.java index 2796538..2cd5128 100644 --- a/src/main/java/de/bstly/board/businesslogic/VoteManager.java +++ b/src/main/java/de/bstly/board/businesslogic/VoteManager.java @@ -27,11 +27,11 @@ public class VoteManager { * Gets the. * * @param author the author - * @param targetType the target type * @param target the target + * @param targetType the target type * @return the vote */ - public Vote get(String author, Types targetType, Long target) { + public Vote get(String author, Long target, Types targetType) { return voteRepository.findOne(qVote.author.eq(author).and(qVote.targetType.eq(targetType)) .and(qVote.target.eq(target))).orElse(null); } diff --git a/src/main/java/de/bstly/board/controller/CommentController.java b/src/main/java/de/bstly/board/controller/CommentController.java index 047ea85..d24739d 100644 --- a/src/main/java/de/bstly/board/controller/CommentController.java +++ b/src/main/java/de/bstly/board/controller/CommentController.java @@ -54,12 +54,12 @@ public class CommentController extends BaseController { /** * Fetch by date. * - * @param target the target - * @param parent the parent - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param descParameter the desc parameter + * @param target the target + * @param parent the parent + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param descParameter the desc parameter * @param ignoreParameter the ignore parameter * @return the page */ @@ -72,11 +72,11 @@ public class CommentController extends BaseController { @RequestParam("date") Optional dateParameter, @RequestParam("desc") Optional descParameter, @RequestParam("ignore") Optional> ignoreParameter) { - + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { sizeParameter = Optional.of(100); } - + if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { dateParameter = Optional.of(Instant.now()); } @@ -92,34 +92,32 @@ public class CommentController extends BaseController { /** * Fetch by username. * - * @param username the username - * @param parent the parent - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param ascParameter the asc parameter + * @param username the username + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param ascParameter the asc parameter * @param ignoreParameter the ignore parameter * @return the page */ @PreAuthorize("isAuthenticated()") @GetMapping({ "/byuser/{username}" }) public Page fetchByUsername(@PathVariable("username") String username, - @PathVariable("parent") Optional parent, @RequestParam("page") Optional pageParameter, @RequestParam("size") Optional sizeParameter, @RequestParam("date") Optional dateParameter, @RequestParam("asc") Optional ascParameter, @RequestParam("ignore") Optional> ignoreParameter) { - + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { sizeParameter = Optional.of(100); } - + if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { dateParameter = Optional.of(Instant.now()); } - Page comments = commentManager.fetchByUsername(username, parent.orElse(null), + Page comments = commentManager.fetchByUsername(username, dateParameter.orElse(Instant.now()), pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false)); List ignore = ignoreParameter.orElse(Lists.newArrayList()); @@ -144,7 +142,7 @@ public class CommentController extends BaseController { /** * Gets the comment. * - * @param id the id + * @param id the id * @param ignoreParameter the ignore parameter * @return the comment */ @@ -166,7 +164,7 @@ public class CommentController extends BaseController { /** * Creates the comment. * - * @param comment the comment + * @param comment the comment * @param ignoreParameter the ignore parameter * @return the comment */ @@ -203,7 +201,7 @@ public class CommentController extends BaseController { /** * Update comment. * - * @param comment the comment + * @param comment the comment * @param ignoreParameter the ignore parameter * @return the comment */ diff --git a/src/main/java/de/bstly/board/controller/EntryController.java b/src/main/java/de/bstly/board/controller/EntryController.java index 029c83d..e3aefe1 100644 --- a/src/main/java/de/bstly/board/controller/EntryController.java +++ b/src/main/java/de/bstly/board/controller/EntryController.java @@ -63,11 +63,11 @@ public class EntryController extends BaseController { /** * Fetch by ranking. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter * @param gravityParameter the gravity parameter - * @param ignoreParameter the ignore parameter + * @param ignoreParameter the ignore parameter * @return the page */ @PreAuthorize("isAuthenticated()") @@ -110,9 +110,9 @@ public class EntryController extends BaseController { /** * Fetch by date. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter * @param ignoreParameter the ignore parameter * @return the page */ @@ -142,11 +142,11 @@ public class EntryController extends BaseController { /** * Fetch by comments. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter * @param gravityParameter the gravity parameter - * @param ignoreParameter the ignore parameter + * @param ignoreParameter the ignore parameter * @return the page */ @PreAuthorize("isAuthenticated()") @@ -183,9 +183,9 @@ public class EntryController extends BaseController { /** * Fetch by last. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter * @param ignoreParameter the ignore parameter * @return the page */ @@ -216,11 +216,11 @@ public class EntryController extends BaseController { /** * Fetch by user. * - * @param username the username - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param ascParameter the asc parameter + * @param username the username + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param ascParameter the asc parameter * @param ignoreParameter the ignore parameter * @return the page */ @@ -253,7 +253,7 @@ public class EntryController extends BaseController { /** * Gets the entry. * - * @param id the id + * @param id the id * @param ignoreParameter the ignore parameter * @return the entry */ @@ -277,7 +277,7 @@ public class EntryController extends BaseController { /** * Creates the entry. * - * @param entry the entry + * @param entry the entry * @param ignoreParameter the ignore parameter * @return the entry */ diff --git a/src/main/java/de/bstly/board/controller/FlagController.java b/src/main/java/de/bstly/board/controller/FlagController.java new file mode 100644 index 0000000..fe5da49 --- /dev/null +++ b/src/main/java/de/bstly/board/controller/FlagController.java @@ -0,0 +1,132 @@ +/** + * + */ +package de.bstly.board.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.bstly.board.businesslogic.CommentManager; +import de.bstly.board.businesslogic.EntryManager; +import de.bstly.board.businesslogic.FlagManager; +import de.bstly.board.controller.support.EntityResponseStatusException; +import de.bstly.board.model.Flag; +import de.bstly.board.model.Types; + +/** + * The Class FlagController. + */ +@RestController +@RequestMapping("/flags") +public class FlagController extends BaseController { + + @Autowired + private FlagManager flagManager; + @Autowired + private EntryManager entryManager; + @Autowired + private CommentManager commentManager; + + /** + * Flag entry. + * + * @param id the id + */ + @PreAuthorize("isAuthenticated()") + @PutMapping("/entry/{id}") + public void flagEntry(@PathVariable("id") Long id) { + if (!entryManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + Flag flag = flagManager.get(getCurrentUsername(), id, Types.entry); + + if (flag != null) { + throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); + } + + flag = new Flag(); + flag.setTarget(id); + flag.setAuthor(getCurrentUsername()); + flag.setTargetType(Types.entry); + flagManager.save(flag); + flagManager.checkEntryFlagStatus(id); + throw new EntityResponseStatusException(HttpStatus.CREATED); + } + + /** + * Unflag entry. + * + * @param id the id + */ + @PreAuthorize("isAuthenticated()") + @DeleteMapping("/entry/{id}") + public void unflagEntry(@PathVariable("id") Long id) { + if (!entryManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + Flag flag = flagManager.get(getCurrentUsername(), id, Types.entry); + if (flag == null) { + throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); + } + + flagManager.delete(flag); + flagManager.checkEntryFlagStatus(id); + } + + /** + * Flag comment. + * + * @param id the id + */ + @PreAuthorize("isAuthenticated()") + @PutMapping("/comment/{id}") + public void flagComment(@PathVariable("id") Long id) { + if (!commentManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + Flag flag = flagManager.get(getCurrentUsername(), id, Types.comment); + + if (flag != null) { + throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); + } + + flag = new Flag(); + flag.setTarget(id); + flag.setAuthor(getCurrentUsername()); + flag.setTargetType(Types.comment); + flagManager.save(flag); + flagManager.checkCommentFlagStatus(id); + throw new EntityResponseStatusException(HttpStatus.CREATED); + } + + /** + * Unflag comment. + * + * @param id the id + */ + @PreAuthorize("isAuthenticated()") + @DeleteMapping("/comment/{id}") + public void unflagComment(@PathVariable("id") Long id) { + if (!commentManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + Flag flag = flagManager.get(getCurrentUsername(), id, Types.comment); + if (flag == null) { + throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); + } + + flagManager.delete(flag); + flagManager.checkCommentFlagStatus(id); + } + +} diff --git a/src/main/java/de/bstly/board/controller/ModerationController.java b/src/main/java/de/bstly/board/controller/ModerationController.java index 4e564fb..3142747 100644 --- a/src/main/java/de/bstly/board/controller/ModerationController.java +++ b/src/main/java/de/bstly/board/controller/ModerationController.java @@ -3,38 +3,134 @@ */ package de.bstly.board.controller; +import java.util.List; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; 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.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.google.common.collect.Lists; import de.bstly.board.businesslogic.CommentManager; import de.bstly.board.businesslogic.EntryManager; +import de.bstly.board.businesslogic.FlagManager; +import de.bstly.board.businesslogic.SettingsManager; import de.bstly.board.businesslogic.UserManager; import de.bstly.board.controller.support.EntityResponseStatusException; +import de.bstly.board.model.Comment; +import de.bstly.board.model.Entry; import de.bstly.board.model.LocalUser; - +import de.bstly.board.model.Types; /** * The Class ModerationController. */ @RestController @RequestMapping("/moderation") -public class ModerationController { +public class ModerationController extends BaseController { - @Autowired private CommentManager commentManager; @Autowired private EntryManager entryManager; @Autowired private UserManager userManager; + @Autowired + private FlagManager flagManager; + @Autowired + private SettingsManager settingsManager; + + /** + * Gets the flagged comments. + * + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter + * @return the flagged comments + */ + @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')") + @GetMapping("/flags/comments") + public Page getFlaggedComments(@RequestParam("page") Optional pageParameter, + @RequestParam("size") Optional sizeParameter, + @RequestParam("asc") Optional ascParameter, + @RequestParam("ignore") Optional> ignoreParameter) { + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { + sizeParameter = Optional.of(100); + } + + Page comments = commentManager.fetchFlagged(pageParameter.orElse(0), + sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false)); + List ignore = ignoreParameter.orElse(Lists.newArrayList("flag", "unflag")); + commentManager.applyMetadata(getCurrentUsername(), comments.getContent(), ignore); + return comments; + } + + /** + * Gets the flagged entries. + * + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter + * @return the flagged entries + */ + @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')") + @GetMapping("/flags/entries") + public Page getFlaggedEntries(@RequestParam("page") Optional pageParameter, + @RequestParam("size") Optional sizeParameter, + @RequestParam("asc") Optional ascParameter, + @RequestParam("ignore") Optional> ignoreParameter) { + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { + sizeParameter = Optional.of(100); + } + + Page entries = entryManager.fetchFlagged(pageParameter.orElse(0), + sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false)); + List ignore = ignoreParameter.orElse(Lists.newArrayList("flag", "unflag", "bookmark", "removeBookmark")); + entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), + entries.getContent(), ignore); + return entries; + } + + /** + * Unflag comment. + * + * @param id the id + */ + @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')") + @DeleteMapping("/flags/comment/{id}") + public void unflagComment(@PathVariable("id") Long id) { + if (!commentManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + flagManager.unflag(id, Types.comment); + } + + /** + * Unflag entry. + * + * @param id the id + */ + @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')") + @DeleteMapping("/flags/entry/{id}") + public void unflagEntry(@PathVariable("id") Long id) { + if (!entryManager.exists(id)) { + throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); + } + + flagManager.unflag(id, Types.entry); + } /** * Delete comment. diff --git a/src/main/java/de/bstly/board/controller/VoteController.java b/src/main/java/de/bstly/board/controller/VoteController.java index 8c25439..2819503 100644 --- a/src/main/java/de/bstly/board/controller/VoteController.java +++ b/src/main/java/de/bstly/board/controller/VoteController.java @@ -69,7 +69,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); } - Vote vote = voteManager.get(getCurrentUsername(), Types.entry, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.entry); if (vote == null) { vote = new Vote(); vote.setTarget(id); @@ -99,7 +99,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.FORBIDDEN); } - Vote vote = voteManager.get(getCurrentUsername(), Types.entry, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.entry); if (vote == null) { vote = new Vote(); vote.setTarget(id); @@ -125,7 +125,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); } - Vote vote = voteManager.get(getCurrentUsername(), Types.entry, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.entry); if (vote == null) { throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); } @@ -161,7 +161,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); } - Vote vote = voteManager.get(getCurrentUsername(), Types.comment, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.comment); if (vote == null) { vote = new Vote(); vote.setTarget(id); @@ -187,7 +187,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); } - Vote vote = voteManager.get(getCurrentUsername(), Types.comment, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.comment); if (vote == null) { vote = new Vote(); vote.setTarget(id); @@ -213,7 +213,7 @@ public class VoteController extends BaseController { throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY); } - Vote vote = voteManager.get(getCurrentUsername(), Types.comment, id); + Vote vote = voteManager.get(getCurrentUsername(), id, Types.comment); if (vote == null) { throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED); } diff --git a/src/main/java/de/bstly/board/model/Comment.java b/src/main/java/de/bstly/board/model/Comment.java index 9585cc1..88987f9 100644 --- a/src/main/java/de/bstly/board/model/Comment.java +++ b/src/main/java/de/bstly/board/model/Comment.java @@ -9,6 +9,8 @@ import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityListeners; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -43,6 +45,9 @@ public class Comment { @Lob @Column(name = "text", nullable = false) private String text; + @Enumerated(EnumType.STRING) + @Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'") + private FlaggedStatus flaggedStatus; @Transient private Map metadata; @@ -154,6 +159,24 @@ public class Comment { this.text = text; } + /** + * Gets the flagged status. + * + * @return the flagged status + */ + public FlaggedStatus getFlaggedStatus() { + return flaggedStatus; + } + + /** + * Sets the flagged status. + * + * @param flaggedStatus the new flagged status + */ + public void setFlaggedStatus(FlaggedStatus flaggedStatus) { + this.flaggedStatus = flaggedStatus; + } + /** * Gets the metadata. * diff --git a/src/main/java/de/bstly/board/model/Entry.java b/src/main/java/de/bstly/board/model/Entry.java index eac21ce..fba9ec6 100644 --- a/src/main/java/de/bstly/board/model/Entry.java +++ b/src/main/java/de/bstly/board/model/Entry.java @@ -22,7 +22,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import com.google.common.collect.Maps; - /** * The Class Entry. */ @@ -31,48 +30,32 @@ import com.google.common.collect.Maps; @EntityListeners({ AuditingEntityListener.class }) public class Entry { - @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false) private Long id; - - @Column(name = "author", nullable = false) private String author; - - @Column(name = "created", nullable = false) private Instant created; - - @Enumerated(EnumType.STRING) @Column(name = "entry_type", nullable = false) private EntryType entryType; - - @Enumerated(EnumType.STRING) @Column(name = "entry_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'") private EntryStatus entryStatus; - - + @Enumerated(EnumType.STRING) + @Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'") + private FlaggedStatus flaggedStatus; @Column(name = "url") private String url; - - @Column(name = "title", nullable = false) private String title; - - @Lob @Column(name = "text") private String text; - - @Transient private Double ranking; - - @Transient private Map metadata; @@ -166,6 +149,24 @@ public class Entry { this.entryStatus = entryStatus; } + /** + * Gets the flagged status. + * + * @return the flagged status + */ + public FlaggedStatus getFlaggedStatus() { + return flaggedStatus; + } + + /** + * Sets the flagged status. + * + * @param flaggedStatus the new flagged status + */ + public void setFlaggedStatus(FlaggedStatus flaggedStatus) { + this.flaggedStatus = flaggedStatus; + } + /** * Gets the url. * diff --git a/src/main/java/de/bstly/board/model/EntryStatus.java b/src/main/java/de/bstly/board/model/EntryStatus.java index 3e930cb..f0ccdfa 100644 --- a/src/main/java/de/bstly/board/model/EntryStatus.java +++ b/src/main/java/de/bstly/board/model/EntryStatus.java @@ -3,17 +3,11 @@ */ package de.bstly.board.model; - /** * The Enum EntryStatus. */ public enum EntryStatus { - - NORMAL, - - ARCHIVED, - - PINNED + NORMAL, ARCHIVED } diff --git a/src/main/java/de/bstly/board/model/EntryType.java b/src/main/java/de/bstly/board/model/EntryType.java index 833ea39..9d7a7b0 100644 --- a/src/main/java/de/bstly/board/model/EntryType.java +++ b/src/main/java/de/bstly/board/model/EntryType.java @@ -3,19 +3,11 @@ */ package de.bstly.board.model; - /** * The Enum EntryType. */ public enum EntryType { - - DISCUSSION, - - INTERN, - - LINK, - - QUESTION + DISCUSSION, INTERN, LINK, QUESTION } diff --git a/src/main/java/de/bstly/board/model/Flag.java b/src/main/java/de/bstly/board/model/Flag.java new file mode 100644 index 0000000..aed42a5 --- /dev/null +++ b/src/main/java/de/bstly/board/model/Flag.java @@ -0,0 +1,107 @@ +/** + * + */ +package de.bstly.board.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +/** + * The Class Flag. + */ +@Entity +@Table(name = "flags") +@EntityListeners({ AuditingEntityListener.class }) +public class Flag { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private Long id; + @Column(name = "target", nullable = false) + private Long target; + @Column(name = "target_type", nullable = false) + private Types targetType; + @Column(name = "author", nullable = false) + private String author; + + /** + * Gets the id. + * + * @return the id + */ + public Long getId() { + return id; + } + + /** + * Sets the id. + * + * @param id the new id + */ + public void setId(Long id) { + this.id = id; + } + + /** + * Gets the target. + * + * @return the target + */ + public Long getTarget() { + return target; + } + + /** + * Sets the target. + * + * @param target the new target + */ + public void setTarget(Long target) { + this.target = target; + } + + /** + * Gets the target type. + * + * @return the target type + */ + public Types getTargetType() { + return targetType; + } + + /** + * Sets the target type. + * + * @param targetType the new target type + */ + public void setTargetType(Types targetType) { + this.targetType = targetType; + } + + /** + * Gets the author. + * + * @return the author + */ + public String getAuthor() { + return author; + } + + /** + * Sets the author. + * + * @param author the new author + */ + public void setAuthor(String author) { + this.author = author; + } + +} diff --git a/src/main/java/de/bstly/board/model/FlaggedStatus.java b/src/main/java/de/bstly/board/model/FlaggedStatus.java new file mode 100644 index 0000000..257a72e --- /dev/null +++ b/src/main/java/de/bstly/board/model/FlaggedStatus.java @@ -0,0 +1,12 @@ +/** + * + */ +package de.bstly.board.model; + +/** + * The Enum FlaggedStatus. + */ +public enum FlaggedStatus { + + NORMAL, FLAGGED, HIDDEN +} diff --git a/src/main/java/de/bstly/board/model/LocalUser.java b/src/main/java/de/bstly/board/model/LocalUser.java index 6b536c7..c6735c3 100644 --- a/src/main/java/de/bstly/board/model/LocalUser.java +++ b/src/main/java/de/bstly/board/model/LocalUser.java @@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.google.common.collect.Maps; - /** * The Class LocalUser. */ @@ -32,50 +31,31 @@ import com.google.common.collect.Maps; @JsonInclude(Include.NON_EMPTY) public class LocalUser { - @Id @Column(name = "username", nullable = false) private String username; - - @Column(name = "external_id", nullable = true) private String externalId; - - @JsonIgnore @Column(name = "password_hash", nullable = true) private String passwordHash; - - @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) @CollectionTable(name = "users_roles") private List roles; - - @Lob @Column(name = "about", nullable = true) private String about; - - @Column(name = "email", nullable = true) private String email; - - @Column(name = "locale", nullable = false, columnDefinition = "varchar(255) default 'en'") private String locale; - - @Column(name = "dark_theme", columnDefinition = "boolean default false") private boolean darkTheme; - - @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) @CollectionTable(name = "users_settings") private Map settings; - - @Transient private Map metadata; diff --git a/src/main/java/de/bstly/board/model/PersistentLogin.java b/src/main/java/de/bstly/board/model/PersistentLogin.java index 6742317..2582513 100644 --- a/src/main/java/de/bstly/board/model/PersistentLogin.java +++ b/src/main/java/de/bstly/board/model/PersistentLogin.java @@ -10,7 +10,6 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; - /** * The Class PersistentLogin. */ @@ -18,20 +17,13 @@ import javax.persistence.Table; @Table(name = "persistent_logins") public class PersistentLogin { - @Column(name = "username", length = 64, nullable = false) private String username; - - @Id @Column(name = "series", length = 64) private String series; - - @Column(name = "token", length = 64, nullable = false) private String token; - - @Column(name = "last_used", nullable = false) private Instant last_used; diff --git a/src/main/java/de/bstly/board/model/Types.java b/src/main/java/de/bstly/board/model/Types.java index c591b24..ece618b 100644 --- a/src/main/java/de/bstly/board/model/Types.java +++ b/src/main/java/de/bstly/board/model/Types.java @@ -3,16 +3,10 @@ */ package de.bstly.board.model; - /** * The Enum Types. */ public enum Types { - - comment, - - entry, - - user + comment, entry, user } diff --git a/src/main/java/de/bstly/board/model/Vote.java b/src/main/java/de/bstly/board/model/Vote.java index 2c68531..86e0459 100644 --- a/src/main/java/de/bstly/board/model/Vote.java +++ b/src/main/java/de/bstly/board/model/Vote.java @@ -21,26 +21,17 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; @Table(name = "votes") @EntityListeners({ AuditingEntityListener.class }) public class Vote { - @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; - - @Column(name = "target", nullable = false) private Long target; - - @Column(name = "target_type", nullable = false) private Types targetType; - - @Column(name = "author", nullable = false) private String author; - - @Column(name = "type", nullable = false) private VoteType type; diff --git a/src/main/java/de/bstly/board/model/VoteType.java b/src/main/java/de/bstly/board/model/VoteType.java index 64fdd17..719b926 100644 --- a/src/main/java/de/bstly/board/model/VoteType.java +++ b/src/main/java/de/bstly/board/model/VoteType.java @@ -3,15 +3,10 @@ */ package de.bstly.board.model; - /** * The Enum VoteType. */ public enum VoteType { - - - up, - - - down + + up, down } diff --git a/src/main/java/de/bstly/board/repository/CommentRepository.java b/src/main/java/de/bstly/board/repository/CommentRepository.java index 1367ab5..7a4ac3b 100644 --- a/src/main/java/de/bstly/board/repository/CommentRepository.java +++ b/src/main/java/de/bstly/board/repository/CommentRepository.java @@ -3,20 +3,12 @@ */ package de.bstly.board.repository; -import java.time.Instant; -import java.util.List; - -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.querydsl.QuerydslPredicateExecutor; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import de.bstly.board.model.Comment; - /** * The Interface CommentRepository. */ @@ -24,57 +16,57 @@ import de.bstly.board.model.Comment; public interface CommentRepository extends JpaRepository, QuerydslPredicateExecutor { - /** - * Find all by ranking and parent. - * - * @param target the target - * @param date the date - * @param gravity the gravity - * @return the list - */ - @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true) - List findAllByRankingAndParent(@Param("target") Long target, - @Param("date") Instant date, @Param("gravity") double gravity); - - /** - * Find all by ranking and parent. - * - * @param target the target - * @param parent the parent - * @param date the date - * @param gravity the gravity - * @return the list - */ - @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true) - List findAllByRankingAndParent(@Param("target") Long target, - @Param("parent") Long parent, @Param("date") Instant date, - @Param("gravity") double gravity); - - /** - * Find all by ranking and parent. - * - * @param target the target - * @param date the date - * @param gravity the gravity - * @param pageable the pageable - * @return the page - */ - @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true) - Page findAllByRankingAndParent(@Param("target") Long target, - @Param("date") Instant date, @Param("gravity") double gravity, Pageable pageable); - - /** - * Find all by ranking and parent. - * - * @param target the target - * @param parent the parent - * @param date the date - * @param gravity the gravity - * @param pageable the pageable - * @return the page - */ - @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true) - Page findAllByRankingAndParent(@Param("target") Long target, - @Param("parent") Long parent, @Param("date") Instant date, - @Param("gravity") double gravity, Pageable pageable); +// /** +// * Find all by ranking and parent. +// * +// * @param target the target +// * @param date the date +// * @param gravity the gravity +// * @return the list +// */ +// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true) +// List findAllByRankingAndParent(@Param("target") Long target, +// @Param("date") Instant date, @Param("gravity") double gravity); +// +// /** +// * Find all by ranking and parent. +// * +// * @param target the target +// * @param parent the parent +// * @param date the date +// * @param gravity the gravity +// * @return the list +// */ +// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true) +// List findAllByRankingAndParent(@Param("target") Long target, +// @Param("parent") Long parent, @Param("date") Instant date, +// @Param("gravity") double gravity); +// +// /** +// * Find all by ranking and parent. +// * +// * @param target the target +// * @param date the date +// * @param gravity the gravity +// * @param pageable the pageable +// * @return the page +// */ +// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true) +// Page findAllByRankingAndParent(@Param("target") Long target, +// @Param("date") Instant date, @Param("gravity") double gravity, Pageable pageable); +// +// /** +// * Find all by ranking and parent. +// * +// * @param target the target +// * @param parent the parent +// * @param date the date +// * @param gravity the gravity +// * @param pageable the pageable +// * @return the page +// */ +// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true) +// Page findAllByRankingAndParent(@Param("target") Long target, +// @Param("parent") Long parent, @Param("date") Instant date, +// @Param("gravity") double gravity, Pageable pageable); } diff --git a/src/main/java/de/bstly/board/repository/EntryRepository.java b/src/main/java/de/bstly/board/repository/EntryRepository.java index f1948c2..bc9c3d3 100644 --- a/src/main/java/de/bstly/board/repository/EntryRepository.java +++ b/src/main/java/de/bstly/board/repository/EntryRepository.java @@ -27,33 +27,23 @@ public interface EntryRepository static final String DOWNVOTES_QUERY = "SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 AND downvote.target_type = 1 GROUP BY downvote.target"; - static final String COMMENTS_QUERY = "SELECT comment.target,MAX(comment.created) as last,COUNT(comment.id) AS count FROM comments as comment GROUP BY comment.target"; + static final String COMMENTS_QUERY = "SELECT comment.target,MAX(comment.created) as last,COUNT(comment.id) AS count FROM comments as comment WHERE comment.flagged_status = 'NORMAL' GROUP BY comment.target"; static final String RANK_CALCULATION_QUERY = "SELECT entry.*, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) as points, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / IF(:gravity > 0, POW(TIMESTAMPDIFF(HOUR, entry.created, :before)+2,:gravity), 1) AS ranking FROM entries AS entry LEFT JOIN (" + UPVOTES_QUERY + ") AS upvote ON upvote.target = entry.id LEFT JOIN (" + DOWNVOTES_QUERY - + ") AS downvote ON downvote.target = entry.id WHERE entry.created < :before AND entry.entry_status = 'NORMAL' ORDER BY ranking DESC, entry.created DESC"; + + ") AS downvote ON downvote.target = entry.id WHERE entry.created < :before AND entry.flagged_status = 'NORMAL' ORDER BY ranking DESC, entry.created DESC"; static final String COMMENT_CALCULATION_QUERY = "SELECT entry.*, IFNULL(comment.count,0) as comments, IFNULL(comment.count,0) / IF(:gravity > 0, POW(TIMESTAMPDIFF(HOUR, comment.last, :before)+2,:gravity), 1) AS ranking FROM entries AS entry LEFT JOIN (" + COMMENTS_QUERY - + ") AS comment ON comment.target = entry.id WHERE entry.created < :before AND entry.entry_status = 'NORMAL' ORDER BY ranking DESC, entry.created DESC"; + + ") AS comment ON comment.target = entry.id WHERE entry.created < :before AND entry.flagged_status = 'NORMAL' ORDER BY ranking DESC, entry.created DESC"; static final String LAST_COMMENT_QUERY = "SELECT entry.* FROM entries AS entry LEFT JOIN (" + COMMENTS_QUERY - + ") AS comment ON comment.target = entry.id WHERE entry.created < :before AND entry.entry_status = 'NORMAL' ORDER BY comment.last DESC, entry.created DESC"; + + ") AS comment ON comment.target = entry.id WHERE entry.created < :before AND entry.flagged_status = 'NORMAL' ORDER BY comment.last DESC, entry.created DESC"; - static final String ARCHIVE_CALCULATION_QUERY = "SELECT entry.*, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) as points, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, entry.created, :before)+2,:gravity) AS ranking FROM entries AS entry LEFT JOIN (" - + UPVOTES_QUERY - + ") AS upvote ON upvote.target = entry.id LEFT JOIN (" - + DOWNVOTES_QUERY - + ") AS downvote ON downvote.target = entry.id WHERE entry.created < :before ORDER BY ranking DESC, entry.created DESC"; - - static final String ADDITIONAL_QUERY = "SELECT entry.*, calculation.ranking, calculation.points FROM entries AS entry LEFT JOIN (" - + RANK_CALCULATION_QUERY - + ") as calculation on calculation.id = entry.id WHERE entry.created < :before ORDER BY calculation.ranking DESC, entry.created DESC"; - - static final String COUNT_QUERY = "SELECT count(*) FROM entries as entry WHERE entry.created < :before"; + static final String COUNT_QUERY = "SELECT count(*) FROM entries as entry WHERE entry.created < :before AND entry.flagged_status = 'NORMAL'"; /** * Find all by ranking. @@ -89,16 +79,4 @@ public interface EntryRepository @Query(value = LAST_COMMENT_QUERY, countQuery = COUNT_QUERY, nativeQuery = true) Page findAllByLastComment(@Param("before") Instant before, Pageable pageable); - /** - * Find all by ranking archive. - * - * @param before the before - * @param gravity the gravity - * @param pageable the pageable - * @return the page - */ - @Query(value = ARCHIVE_CALCULATION_QUERY, countQuery = COUNT_QUERY, nativeQuery = true) - Page findAllByRankingArchive(@Param("before") Instant before, - @Param("gravity") double gravity, Pageable pageable); - } diff --git a/src/main/java/de/bstly/board/repository/FlagRepository.java b/src/main/java/de/bstly/board/repository/FlagRepository.java new file mode 100644 index 0000000..30fd19a --- /dev/null +++ b/src/main/java/de/bstly/board/repository/FlagRepository.java @@ -0,0 +1,18 @@ +/** + * + */ +package de.bstly.board.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +import de.bstly.board.model.Flag; + +/** + * The Interface FlagRepository. + */ +@Repository +public interface FlagRepository extends JpaRepository, QuerydslPredicateExecutor { + +} diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties deleted file mode 100644 index 326f99d..0000000 --- a/src/main/resources/messages.properties +++ /dev/null @@ -1,46 +0,0 @@ -# index -login=Login -login.error=Credentials not valid. -login.external=Login with {0} -logout=Logout -pagination.first=First -pagination.prev=Previous -pagination.next=Next -pagination.last=Last -username=Username -password=Password -rememberMe=Remember Me -settings=Settings -submit=Submit -top=Top -new=New - -comments={0} comments - - -entry.title=title -entry.url=url -entry.text=text -entry.type=type -entry.vote=vote -entry.unvote=unvote -entry.votes={0} points -entry.createdBy=by {0} - -entryType.LINK=link -entryType.DISCUSSION=discussion -entryType.QUESTION=question -entryType.INTERN=intern - -entryType.LINK.bicon=bi-link-45deg -entryType.DISCUSSION.bicon=bi-chat-text -entryType.QUESTION.bicon=bi-question-square -entryType.INTERN.bicon=bi-shield-lock - -REQUIRED.entry.title=title is required -REQUIRED.entry.type=type is required -REQUIRED.entry.url=url is required -INVALID.entry.url=url is invalid - -entries.empty=No entries found. -submit.info=Create a new entry.