mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
add a button for testing push notification settings
This commit is contained in:
@@ -40,9 +40,9 @@ public class FeedUpdateNotifier {
|
||||
}
|
||||
|
||||
UserSettings settings = unitOfWork.call(() -> userSettingsDAO.findByUser(sub.getUser()));
|
||||
if (settings != null && settings.getPushNotificationType() != null) {
|
||||
if (settings != null && settings.getPushNotifications() != null && settings.getPushNotifications().getType() != null) {
|
||||
for (FeedEntry entry : entries) {
|
||||
pushNotificationService.notify(settings, sub, entry);
|
||||
pushNotificationService.notify(settings.getPushNotifications(), sub, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.commafeed.backend.model;
|
||||
import java.sql.Types;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
@@ -144,22 +146,6 @@ public class UserSettings extends AbstractModel {
|
||||
private boolean unreadCountFavicon;
|
||||
private boolean disablePullToRefresh;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "push_notification_type", length = 16)
|
||||
private PushNotificationType pushNotificationType;
|
||||
|
||||
@Column(name = "push_notification_server_url", length = 1024)
|
||||
private String pushNotificationServerUrl;
|
||||
|
||||
@Column(name = "push_notification_user_id", length = 512)
|
||||
private String pushNotificationUserId;
|
||||
|
||||
@Column(name = "push_notification_user_secret", length = 512)
|
||||
private String pushNotificationUserSecret;
|
||||
|
||||
@Column(name = "push_notification_topic", length = 256)
|
||||
private String pushNotificationTopic;
|
||||
|
||||
private boolean email;
|
||||
private boolean gmail;
|
||||
private boolean facebook;
|
||||
@@ -169,4 +155,28 @@ public class UserSettings extends AbstractModel {
|
||||
private boolean instapaper;
|
||||
private boolean buffer;
|
||||
|
||||
@Embedded
|
||||
private PushNotificationUserSettings pushNotifications = new PushNotificationUserSettings();
|
||||
|
||||
@Embeddable
|
||||
@Getter
|
||||
@Setter
|
||||
public static class PushNotificationUserSettings {
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "push_notification_type", length = 16)
|
||||
private PushNotificationType type;
|
||||
|
||||
@Column(name = "push_notification_server_url", length = 1024)
|
||||
private String serverUrl;
|
||||
|
||||
@Column(name = "push_notification_user_id", length = 512)
|
||||
private String userId;
|
||||
|
||||
@Column(name = "push_notification_user_secret", length = 512)
|
||||
private String userSecret;
|
||||
|
||||
@Column(name = "push_notification_topic", length = 256)
|
||||
private String topic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.commafeed.backend.HttpClientFactory;
|
||||
import com.commafeed.backend.Urls;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
|
||||
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -44,12 +44,12 @@ public class PushNotificationService {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public void notify(UserSettings settings, FeedSubscription subscription, FeedEntry entry) {
|
||||
if (!config.pushNotifications().enabled() || settings.getPushNotificationType() == null) {
|
||||
public void notify(PushNotificationUserSettings settings, FeedSubscription subscription, FeedEntry entry) {
|
||||
if (!config.pushNotifications().enabled() || settings.getType() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("sending {} push notification for entry {} in feed {}", settings.getPushNotificationType(), entry.getId(),
|
||||
log.debug("sending {} push notification for entry {} in feed {}", settings.getType(), entry.getId(),
|
||||
subscription.getFeed().getId());
|
||||
String entryTitle = entry.getContent() != null ? entry.getContent().getTitle() : null;
|
||||
String entryUrl = entry.getUrl();
|
||||
@@ -60,11 +60,11 @@ public class PushNotificationService {
|
||||
}
|
||||
|
||||
try {
|
||||
switch (settings.getPushNotificationType()) {
|
||||
switch (settings.getType()) {
|
||||
case NTFY -> sendNtfy(settings, feedTitle, entryTitle, entryUrl);
|
||||
case GOTIFY -> sendGotify(settings, feedTitle, entryTitle, entryUrl);
|
||||
case PUSHOVER -> sendPushover(settings, feedTitle, entryTitle, entryUrl);
|
||||
default -> throw new IllegalStateException("unsupported notification type: " + settings.getPushNotificationType());
|
||||
default -> throw new IllegalStateException("unsupported notification type: " + settings.getType());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new PushNotificationException("Failed to send external notification", e);
|
||||
@@ -73,9 +73,9 @@ public class PushNotificationService {
|
||||
meter.mark();
|
||||
}
|
||||
|
||||
private void sendNtfy(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
|
||||
String serverUrl = Urls.removeTrailingSlash(settings.getPushNotificationServerUrl());
|
||||
String topic = settings.getPushNotificationTopic();
|
||||
private void sendNtfy(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
|
||||
String serverUrl = Urls.removeTrailingSlash(settings.getServerUrl());
|
||||
String topic = settings.getTopic();
|
||||
|
||||
if (StringUtils.isBlank(serverUrl) || StringUtils.isBlank(topic)) {
|
||||
log.warn("ntfy notification skipped: missing server URL or topic");
|
||||
@@ -91,8 +91,8 @@ public class PushNotificationService {
|
||||
request.addHeader("Click", entryUrl);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(settings.getPushNotificationUserSecret())) {
|
||||
request.addHeader("Authorization", "Bearer " + settings.getPushNotificationUserSecret());
|
||||
if (StringUtils.isNotBlank(settings.getUserSecret())) {
|
||||
request.addHeader("Authorization", "Bearer " + settings.getUserSecret());
|
||||
}
|
||||
|
||||
httpClient.execute(request, response -> {
|
||||
@@ -103,9 +103,10 @@ public class PushNotificationService {
|
||||
});
|
||||
}
|
||||
|
||||
private void sendGotify(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
|
||||
String serverUrl = Urls.removeTrailingSlash(settings.getPushNotificationServerUrl());
|
||||
String token = settings.getPushNotificationUserSecret();
|
||||
private void sendGotify(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl)
|
||||
throws IOException {
|
||||
String serverUrl = Urls.removeTrailingSlash(settings.getServerUrl());
|
||||
String token = settings.getUserSecret();
|
||||
|
||||
if (StringUtils.isBlank(serverUrl) || StringUtils.isBlank(token)) {
|
||||
log.warn("gotify notification skipped: missing server URL or token");
|
||||
@@ -134,9 +135,10 @@ public class PushNotificationService {
|
||||
});
|
||||
}
|
||||
|
||||
private void sendPushover(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
|
||||
String token = settings.getPushNotificationUserSecret();
|
||||
String userKey = settings.getPushNotificationUserId();
|
||||
private void sendPushover(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl)
|
||||
throws IOException {
|
||||
String token = settings.getUserSecret();
|
||||
String userKey = settings.getUserId();
|
||||
|
||||
if (StringUtils.isBlank(token) || StringUtils.isBlank(userKey)) {
|
||||
log.warn("pushover notification skipped: missing token or user key");
|
||||
|
||||
@@ -38,19 +38,26 @@ import com.commafeed.backend.Urls;
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.dao.UserRoleDAO;
|
||||
import com.commafeed.backend.dao.UserSettingsDAO;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.model.UserSettings.IconDisplayMode;
|
||||
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingMode;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||
import com.commafeed.backend.model.UserSettings.ScrollMode;
|
||||
import com.commafeed.backend.service.MailService;
|
||||
import com.commafeed.backend.service.PasswordEncryptionService;
|
||||
import com.commafeed.backend.service.PushNotificationService;
|
||||
import com.commafeed.backend.service.UserService;
|
||||
import com.commafeed.backend.service.db.DatabaseStartupService;
|
||||
import com.commafeed.frontend.model.Settings;
|
||||
import com.commafeed.frontend.model.Settings.PushNotificationSettings;
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.frontend.model.request.InitialSetupRequest;
|
||||
import com.commafeed.frontend.model.request.PasswordResetConfirmationRequest;
|
||||
@@ -84,6 +91,7 @@ public class UserREST {
|
||||
private final MailService mailService;
|
||||
private final CommaFeedConfiguration config;
|
||||
private final UriInfo uri;
|
||||
private final PushNotificationService pushNotificationService;
|
||||
|
||||
@Path("/settings")
|
||||
@GET
|
||||
@@ -126,11 +134,13 @@ public class UserREST {
|
||||
s.setDisablePullToRefresh(settings.isDisablePullToRefresh());
|
||||
s.setPrimaryColor(settings.getPrimaryColor());
|
||||
|
||||
s.getPushNotificationSettings().setType(settings.getPushNotificationType());
|
||||
s.getPushNotificationSettings().setServerUrl(settings.getPushNotificationServerUrl());
|
||||
s.getPushNotificationSettings().setUserId(settings.getPushNotificationUserId());
|
||||
s.getPushNotificationSettings().setUserSecret(settings.getPushNotificationUserSecret());
|
||||
s.getPushNotificationSettings().setTopic(settings.getPushNotificationTopic());
|
||||
if (settings.getPushNotifications() != null) {
|
||||
s.getPushNotificationSettings().setType(settings.getPushNotifications().getType());
|
||||
s.getPushNotificationSettings().setServerUrl(settings.getPushNotifications().getServerUrl());
|
||||
s.getPushNotificationSettings().setUserId(settings.getPushNotifications().getUserId());
|
||||
s.getPushNotificationSettings().setUserSecret(settings.getPushNotifications().getUserSecret());
|
||||
s.getPushNotificationSettings().setTopic(settings.getPushNotifications().getTopic());
|
||||
}
|
||||
} else {
|
||||
s.setReadingMode(ReadingMode.UNREAD);
|
||||
s.setReadingOrder(ReadingOrder.DESC);
|
||||
@@ -196,11 +206,13 @@ public class UserREST {
|
||||
s.setDisablePullToRefresh(settings.isDisablePullToRefresh());
|
||||
s.setPrimaryColor(settings.getPrimaryColor());
|
||||
|
||||
s.setPushNotificationType(settings.getPushNotificationSettings().getType());
|
||||
s.setPushNotificationServerUrl(settings.getPushNotificationSettings().getServerUrl());
|
||||
s.setPushNotificationUserId(settings.getPushNotificationSettings().getUserId());
|
||||
s.setPushNotificationUserSecret(settings.getPushNotificationSettings().getUserSecret());
|
||||
s.setPushNotificationTopic(settings.getPushNotificationSettings().getTopic());
|
||||
PushNotificationUserSettings ps = new PushNotificationUserSettings();
|
||||
ps.setType(settings.getPushNotificationSettings().getType());
|
||||
ps.setServerUrl(settings.getPushNotificationSettings().getServerUrl());
|
||||
ps.setUserId(settings.getPushNotificationSettings().getUserId());
|
||||
ps.setUserSecret(settings.getPushNotificationSettings().getUserSecret());
|
||||
ps.setTopic(settings.getPushNotificationSettings().getTopic());
|
||||
s.setPushNotifications(ps);
|
||||
|
||||
s.setEmail(settings.getSharingSettings().isEmail());
|
||||
s.setGmail(settings.getSharingSettings().isGmail());
|
||||
@@ -216,6 +228,37 @@ public class UserREST {
|
||||
|
||||
}
|
||||
|
||||
@Path("/pushNotificationTest")
|
||||
@POST
|
||||
@Transactional
|
||||
@Operation(summary = "Send a test push notification")
|
||||
public Response sendTestPushNotification(@Parameter(required = true) PushNotificationSettings settings) {
|
||||
FeedSubscription sub = new FeedSubscription();
|
||||
sub.setTitle("CommaFeed Test Feed");
|
||||
sub.setFeed(new Feed());
|
||||
|
||||
FeedEntryContent content = new FeedEntryContent();
|
||||
content.setTitle("Test Entry");
|
||||
|
||||
FeedEntry entry = new FeedEntry();
|
||||
entry.setContent(content);
|
||||
|
||||
PushNotificationUserSettings pushSettings = new PushNotificationUserSettings();
|
||||
pushSettings.setType(settings.getType());
|
||||
pushSettings.setServerUrl(settings.getServerUrl());
|
||||
pushSettings.setUserId(settings.getUserId());
|
||||
pushSettings.setUserSecret(settings.getUserSecret());
|
||||
pushSettings.setTopic(settings.getTopic());
|
||||
|
||||
try {
|
||||
pushNotificationService.notify(pushSettings, sub, entry);
|
||||
} catch (Exception e) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getCause().getMessage()).type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/profile")
|
||||
@GET
|
||||
@Transactional
|
||||
|
||||
@@ -22,8 +22,8 @@ import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.model.UserSettings.PushNotificationType;
|
||||
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
|
||||
|
||||
@ExtendWith(MockServerExtension.class)
|
||||
class PushNotificationServiceTest {
|
||||
@@ -31,7 +31,7 @@ class PushNotificationServiceTest {
|
||||
private MockServerClient mockServerClient;
|
||||
private PushNotificationService pushNotificationService;
|
||||
private CommaFeedConfiguration config;
|
||||
private UserSettings userSettings;
|
||||
private PushNotificationUserSettings userSettings;
|
||||
private FeedSubscription subscription;
|
||||
private FeedEntry entry;
|
||||
|
||||
@@ -51,7 +51,7 @@ class PushNotificationServiceTest {
|
||||
|
||||
this.pushNotificationService = new PushNotificationService(httpClientFactory, metricRegistry, config);
|
||||
|
||||
this.userSettings = new UserSettings();
|
||||
this.userSettings = new PushNotificationUserSettings();
|
||||
|
||||
this.subscription = createSubscription("Test Feed");
|
||||
this.entry = createEntry("Test Entry", "http://example.com/entry");
|
||||
@@ -59,10 +59,10 @@ class PushNotificationServiceTest {
|
||||
|
||||
@Test
|
||||
void testNtfyNotification() {
|
||||
userSettings.setPushNotificationType(PushNotificationType.NTFY);
|
||||
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setPushNotificationTopic("test-topic");
|
||||
userSettings.setPushNotificationUserSecret("test-secret");
|
||||
userSettings.setType(PushNotificationType.NTFY);
|
||||
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setTopic("test-topic");
|
||||
userSettings.setUserSecret("test-secret");
|
||||
|
||||
mockServerClient.when(HttpRequest.request()
|
||||
.withMethod("POST")
|
||||
@@ -77,9 +77,9 @@ class PushNotificationServiceTest {
|
||||
|
||||
@Test
|
||||
void testGotifyNotification() {
|
||||
userSettings.setPushNotificationType(PushNotificationType.GOTIFY);
|
||||
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setPushNotificationUserSecret("gotify-token");
|
||||
userSettings.setType(PushNotificationType.GOTIFY);
|
||||
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setUserSecret("gotify-token");
|
||||
|
||||
mockServerClient.when(HttpRequest.request()
|
||||
.withMethod("POST")
|
||||
@@ -107,9 +107,9 @@ class PushNotificationServiceTest {
|
||||
@Test
|
||||
void testPushNotificationDisabled() {
|
||||
Mockito.when(config.pushNotifications().enabled()).thenReturn(false);
|
||||
userSettings.setPushNotificationType(PushNotificationType.NTFY);
|
||||
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setPushNotificationTopic("test-topic");
|
||||
userSettings.setType(PushNotificationType.NTFY);
|
||||
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setTopic("test-topic");
|
||||
|
||||
Assertions.assertDoesNotThrow(() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
mockServerClient.verifyZeroInteractions();
|
||||
|
||||
Reference in New Issue
Block a user