updated dependencies, migrate RandomStringUtils, prepare notifications
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.2.4</version>
|
<version>3.4.5</version>
|
||||||
<relativePath />
|
<relativePath />
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package de.bstly.board.businesslogic;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import de.bstly.board.businesslogic.notification.NotificationProvider;
|
||||||
|
import de.bstly.board.model.LocalUser;
|
||||||
|
import de.bstly.board.model.Notification;
|
||||||
|
import de.bstly.board.model.QNotification;
|
||||||
|
import de.bstly.board.model.support.Notificationable;
|
||||||
|
import de.bstly.board.repository.NotificationRepository;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NotificationsManager implements SmartInitializingSingleton {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(NotificationsManager.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotificationRepository notificationRepository;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private List<NotificationProvider> providers;
|
||||||
|
|
||||||
|
private QNotification qNotification;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
providers = Lists.newArrayList(applicationContext.getBeansOfType(NotificationProvider.class).values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processNotificationable(Notificationable notificationable) {
|
||||||
|
logger.info("Created new " + notificationable.getType() + " [" + notificationable.getId() + "] by "
|
||||||
|
+ notificationable.getAuthor() + " at " + notificationable.getCreated());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification geNotification(String username, Notificationable notificationable) {
|
||||||
|
return notificationRepository.findOne(qNotification.targetType.eq(notificationable.getType())
|
||||||
|
.and(qNotification.owner.eq(username))
|
||||||
|
.and(qNotification.target.eq(notificationable.getId()).or(qNotification.target.isNull()))).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification createNotification(Notification notification) {
|
||||||
|
return notificationRepository.save(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification updateNotification(Notification notification) {
|
||||||
|
return notificationRepository.save(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteNotification(Long id) {
|
||||||
|
notificationRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getUsernames(Notificationable notificationable) {
|
||||||
|
List<Notification> notifications = Lists
|
||||||
|
.newArrayList(notificationRepository.findAll(qNotification.targetType.eq(notificationable.getType())
|
||||||
|
.and(qNotification.target.eq(notificationable.getId()).or(qNotification.target.isNull())).and(qNotification.disabled.isFalse())));
|
||||||
|
|
||||||
|
return notifications.stream().map(Notification::getOwner).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
protected void processNotificationable(String username, Notificationable notificationable) {
|
||||||
|
LocalUser user = userManager.getByUsername(username);
|
||||||
|
for (NotificationProvider provider : providers) {
|
||||||
|
if (user.getSettings() != null && user.getSettings().get(provider.getId()) == "true") {
|
||||||
|
provider.processNotificationable(user, notificationable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -92,7 +92,7 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet
|
|||||||
public void afterSingletonsInstantiated() {
|
public void afterSingletonsInstantiated() {
|
||||||
if (!localUserRepository.exists(qLocalUser.roles.contains("ROLE_ADMIN"))) {
|
if (!localUserRepository.exists(qLocalUser.roles.contains("ROLE_ADMIN"))) {
|
||||||
if (!StringUtils.hasText(adminPassword)) {
|
if (!StringUtils.hasText(adminPassword)) {
|
||||||
adminPassword = RandomStringUtils.random(24, true, true);
|
adminPassword = RandomStringUtils.secure().next(24, true, true);
|
||||||
logger.error("password for 'admin': " + adminPassword);
|
logger.error("password for 'admin': " + adminPassword);
|
||||||
}
|
}
|
||||||
LocalUser admin = new LocalUser();
|
LocalUser admin = new LocalUser();
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package de.bstly.board.businesslogic.notification;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import de.bstly.board.model.LocalUser;
|
||||||
|
import de.bstly.board.model.support.Notificationable;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class EmailNotificationProvider implements NotificationProvider{
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JavaMailSender javaMailSender;
|
||||||
|
|
||||||
|
@Value("bstly.board.email.from")
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "notificationsEmail";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
@Override
|
||||||
|
public void processNotificationable(LocalUser user, Notificationable notificationable) {
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setFrom(from);
|
||||||
|
message.setTo(user.getEmail());
|
||||||
|
message.setSubject("New " + notificationable.getType());
|
||||||
|
message.setText("Created new " + notificationable.getType() +" by "
|
||||||
|
+ notificationable.getAuthor() + " at " + notificationable.getCreated());
|
||||||
|
javaMailSender.send(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package de.bstly.board.businesslogic.notification;
|
||||||
|
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
|
import de.bstly.board.model.LocalUser;
|
||||||
|
import de.bstly.board.model.support.Notificationable;
|
||||||
|
|
||||||
|
public interface NotificationProvider {
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
@Async
|
||||||
|
void processNotificationable(LocalUser user, Notificationable notificationable);
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package de.bstly.board.businesslogic.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import de.bstly.board.businesslogic.NotificationsManager;
|
||||||
|
import de.bstly.board.model.support.Notificationable;
|
||||||
|
import jakarta.persistence.PostPersist;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NotificationEntityListener {
|
||||||
|
|
||||||
|
private static NotificationsManager notificationsManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setEntityProviderManager(NotificationsManager notificationsManager) {
|
||||||
|
NotificationEntityListener.notificationsManager = notificationsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostPersist
|
||||||
|
public void postPersist(Notificationable notificationable) {
|
||||||
|
if (notificationsManager != null) {
|
||||||
|
notificationsManager.processNotificationable(notificationable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -124,8 +124,8 @@ public class DebugController extends BaseController {
|
|||||||
entry.setEntryType(EntryType.INTERN);
|
entry.setEntryType(EntryType.INTERN);
|
||||||
entry.setAuthor(username);
|
entry.setAuthor(username);
|
||||||
entry.setCreated(Instant.now().minus(splittableRandom.nextLong(0, entryAge), ChronoUnit.SECONDS));
|
entry.setCreated(Instant.now().minus(splittableRandom.nextLong(0, entryAge), ChronoUnit.SECONDS));
|
||||||
entry.setTitle(RandomStringUtils.randomAscii(splittableRandom.nextInt(10, 250)));
|
entry.setTitle(RandomStringUtils.secure().nextAscii(splittableRandom.nextInt(10, 250)));
|
||||||
entry.setText(RandomStringUtils.randomAscii(splittableRandom.nextInt(0, 2500)));
|
entry.setText(RandomStringUtils.secure().nextAscii(splittableRandom.nextInt(0, 2500)));
|
||||||
entry.setEntryStatus(EntryStatus.NORMAL);
|
entry.setEntryStatus(EntryStatus.NORMAL);
|
||||||
entry.setFlaggedStatus(FlaggedStatus.NORMAL);
|
entry.setFlaggedStatus(FlaggedStatus.NORMAL);
|
||||||
entry = entryManager.save(entry);
|
entry = entryManager.save(entry);
|
||||||
@@ -150,7 +150,7 @@ public class DebugController extends BaseController {
|
|||||||
Comment comment = new Comment();
|
Comment comment = new Comment();
|
||||||
comment.setTarget(target);
|
comment.setTarget(target);
|
||||||
comment.setAuthor("user" + splittableRandom.nextLong(0, userCount));
|
comment.setAuthor("user" + splittableRandom.nextLong(0, userCount));
|
||||||
comment.setText(RandomStringUtils.randomAscii(splittableRandom.nextInt(0, 2500)));
|
comment.setText(RandomStringUtils.secure().nextAscii(splittableRandom.nextInt(0, 2500)));
|
||||||
comment.setFlaggedStatus(FlaggedStatus.NORMAL);
|
comment.setFlaggedStatus(FlaggedStatus.NORMAL);
|
||||||
comment.setCreated(Instant.now().minus(
|
comment.setCreated(Instant.now().minus(
|
||||||
splittableRandom.nextLong(0, (Instant.now().toEpochMilli() - date.toEpochMilli()) / 1000),
|
splittableRandom.nextLong(0, (Instant.now().toEpochMilli() - date.toEpochMilli()) / 1000),
|
||||||
@@ -183,7 +183,7 @@ public class DebugController extends BaseController {
|
|||||||
comment.setTarget(target);
|
comment.setTarget(target);
|
||||||
comment.setParent(parent);
|
comment.setParent(parent);
|
||||||
comment.setAuthor("user" + splittableRandom.nextLong(0, userCount));
|
comment.setAuthor("user" + splittableRandom.nextLong(0, userCount));
|
||||||
comment.setText(RandomStringUtils.randomAscii(splittableRandom.nextInt(0, 2500)));
|
comment.setText(RandomStringUtils.secure().nextAscii(splittableRandom.nextInt(0, 2500)));
|
||||||
comment.setFlaggedStatus(FlaggedStatus.NORMAL);
|
comment.setFlaggedStatus(FlaggedStatus.NORMAL);
|
||||||
comment.setCreated(Instant.now().minus(
|
comment.setCreated(Instant.now().minus(
|
||||||
splittableRandom.nextLong(0, (Instant.now().toEpochMilli() - date.toEpochMilli()) / 1000),
|
splittableRandom.nextLong(0, (Instant.now().toEpochMilli() - date.toEpochMilli()) / 1000),
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.board.controller;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PatchMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import de.bstly.board.businesslogic.NotificationsManager;
|
||||||
|
import de.bstly.board.model.Notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class NotificationController.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/notifications")
|
||||||
|
public class NotificationController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotificationsManager notificationsManager;
|
||||||
|
|
||||||
|
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PostMapping()
|
||||||
|
public Notification createNotification(@RequestBody Notification notification) {
|
||||||
|
notification.setOwner(getCurrentUsername());
|
||||||
|
return notificationsManager.createNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PatchMapping()
|
||||||
|
public Notification updateNotification(@RequestBody Notification notification) {
|
||||||
|
notification.setOwner(getCurrentUsername());
|
||||||
|
return notificationsManager.updateNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@DeleteMapping("{id}")
|
||||||
|
public void deleteNotification(@PathVariable("id") Long id) {
|
||||||
|
notificationsManager.deleteNotification(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.board.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EntityListeners;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
|
import de.bstly.board.model.support.Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Flag.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "notifications")
|
||||||
|
@EntityListeners({ AuditingEntityListener.class })
|
||||||
|
public class Notification {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "target")
|
||||||
|
private Long target;
|
||||||
|
@Column(name = "parent")
|
||||||
|
private Long parent;
|
||||||
|
@Column(name = "target_type", nullable = false)
|
||||||
|
private Types targetType;
|
||||||
|
@Column(name = "owner", nullable = false)
|
||||||
|
private String owner;
|
||||||
|
@Column(name = "disabled", nullable = false)
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(Long parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 owner.
|
||||||
|
*
|
||||||
|
* @return the owner
|
||||||
|
*/
|
||||||
|
public String getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the owner.
|
||||||
|
*
|
||||||
|
* @param owner the new owner
|
||||||
|
*/
|
||||||
|
public void setOwner(String owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisabled(boolean disabled) {
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package de.bstly.board.model.support;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public interface Notificationable {
|
||||||
|
|
||||||
|
Long getId();
|
||||||
|
|
||||||
|
String getAuthor();
|
||||||
|
|
||||||
|
Instant getCreated();
|
||||||
|
|
||||||
|
Types getType();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.Notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface NotifcationRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface NotificationRepository extends JpaRepository<Notification, Long>, QuerydslPredicateExecutor<Notification> {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user